Merge remote-tracking branch 'strace/master' into HEAD

Change-Id: I71324955ac973323aa790485c240e553272ff266
diff --git a/Makefile.am b/Makefile.am
index 48fe1d7..8193c9e 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -77,6 +77,7 @@
 	personality.c	\
 	prctl.c		\
 	printmode.c	\
+	printsiginfo.c	\
 	printstat.h	\
 	process.c	\
 	process_vm.c	\
@@ -92,6 +93,7 @@
 	sched.c		\
 	scsi.c		\
 	seccomp.c	\
+	sigaltstack.c	\
 	signal.c	\
 	sigreturn.c	\
 	sock.c		\
@@ -164,77 +166,173 @@
 	linux/32/syscallent.h		\
 	linux/64/ioctls_inc.h		\
 	linux/64/syscallent.h		\
+	linux/aarch64/arch_regs.c	\
 	linux/aarch64/arch_regs.h	\
+	linux/aarch64/arch_sigreturn.c	\
 	linux/aarch64/errnoent1.h	\
+	linux/aarch64/get_error.c	\
+	linux/aarch64/get_scno.c	\
+	linux/aarch64/get_syscall_args.c\
 	linux/aarch64/ioctls_arch0.h	\
 	linux/aarch64/ioctls_arch1.h	\
 	linux/aarch64/ioctls_inc0.h	\
 	linux/aarch64/ioctls_inc1.h	\
+	linux/aarch64/print_pc.c	\
 	linux/aarch64/signalent1.h	\
 	linux/aarch64/syscallent.h	\
 	linux/aarch64/syscallent1.h	\
+	linux/alpha/arch_getrval2.c	\
+	linux/alpha/arch_regs.c		\
 	linux/alpha/arch_regs.h		\
+	linux/alpha/arch_sigreturn.c	\
 	linux/alpha/errnoent.h		\
+	linux/alpha/get_error.c		\
+	linux/alpha/get_scno.c		\
+	linux/alpha/get_syscall_args.c	\
+	linux/alpha/get_syscall_result.c\
 	linux/alpha/ioctls_arch0.h	\
 	linux/alpha/ioctls_inc0.h	\
+	linux/alpha/print_pc.c		\
 	linux/alpha/signalent.h		\
 	linux/alpha/syscallent.h	\
 	linux/alpha/userent.h		\
+	linux/arc/arch_regs.c		\
+	linux/arc/get_error.c		\
+	linux/arc/get_scno.c		\
+	linux/arc/get_syscall_args.c	\
 	linux/arc/ioctls_arch0.h	\
 	linux/arc/ioctls_inc0.h		\
+	linux/arc/print_pc.c		\
 	linux/arc/syscallent.h		\
 	linux/arch_regs.h		\
+	linux/arch_sigreturn.c		\
+	linux/arm/arch_regs.c		\
 	linux/arm/arch_regs.h		\
+	linux/arm/arch_sigreturn.c	\
+	linux/arm/get_error.c		\
+	linux/arm/get_scno.c		\
+	linux/arm/get_syscall_args.c	\
 	linux/arm/ioctls_arch0.h	\
 	linux/arm/ioctls_inc0.h		\
+	linux/arm/print_pc.c		\
 	linux/arm/syscallent.h		\
 	linux/arm/userent.h		\
+	linux/avr32/arch_regs.c		\
+	linux/avr32/get_error.c		\
+	linux/avr32/get_scno.c		\
+	linux/avr32/get_syscall_args.c	\
 	linux/avr32/ioctls_arch0.h	\
 	linux/avr32/ioctls_inc0.h	\
+	linux/avr32/print_pc.c		\
 	linux/avr32/syscallent.h	\
 	linux/avr32/userent.h		\
+	linux/bfin/arch_regs.c		\
+	linux/bfin/get_error.c		\
+	linux/bfin/get_scno.c		\
+	linux/bfin/get_syscall_args.c	\
+	linux/bfin/get_syscall_result.c	\
 	linux/bfin/ioctls_arch0.h	\
 	linux/bfin/ioctls_inc0.h	\
+	linux/bfin/print_pc.c		\
 	linux/bfin/syscallent.h		\
 	linux/bfin/userent.h		\
+	linux/crisv10/arch_regs.c	\
+	linux/crisv10/arch_sigreturn.c	\
+	linux/crisv10/get_error.c	\
+	linux/crisv10/get_scno.c	\
+	linux/crisv10/get_syscall_args.c	\
+	linux/crisv10/get_syscall_result.c	\
+	linux/crisv10/print_pc.c	\
 	linux/crisv10/userent.h		\
+	linux/crisv32/arch_regs.c	\
+	linux/crisv32/arch_sigreturn.c	\
+	linux/crisv32/get_error.c	\
+	linux/crisv32/get_scno.c	\
+	linux/crisv32/get_syscall_args.c	\
+	linux/crisv32/get_syscall_result.c	\
+	linux/crisv32/print_pc.c	\
 	linux/crisv32/userent.h		\
 	linux/dummy.h			\
 	linux/errnoent.h		\
+	linux/hppa/arch_regs.c		\
 	linux/hppa/arch_regs.h		\
 	linux/hppa/errnoent.h		\
+	linux/hppa/get_error.c		\
+	linux/hppa/get_scno.c		\
+	linux/hppa/get_syscall_args.c	\
+	linux/hppa/get_syscall_result.c	\
 	linux/hppa/ioctls_arch0.h	\
 	linux/hppa/ioctls_inc0.h	\
+	linux/hppa/print_pc.c		\
 	linux/hppa/signalent.h		\
 	linux/hppa/syscallent.h		\
+	linux/i386/arch_regs.c		\
 	linux/i386/arch_regs.h		\
+	linux/i386/arch_sigreturn.c	\
+	linux/i386/get_error.c		\
+	linux/i386/get_scno.c		\
+	linux/i386/get_syscall_args.c	\
 	linux/i386/ioctls_arch0.h	\
 	linux/i386/ioctls_inc0.h	\
+	linux/i386/print_pc.c		\
 	linux/i386/syscallent.h		\
 	linux/i386/userent.h		\
 	linux/i386/userent0.h		\
+	linux/ia64/arch_getrval2.c	\
+	linux/ia64/arch_regs.c		\
 	linux/ia64/arch_regs.h		\
+	linux/ia64/arch_sigreturn.c	\
+	linux/ia64/get_error.c		\
+	linux/ia64/get_scno.c		\
+	linux/ia64/get_syscall_args.c	\
 	linux/ia64/ioctls_arch0.h	\
 	linux/ia64/ioctls_inc0.h	\
+	linux/ia64/print_pc.c		\
 	linux/ia64/syscallent.h		\
 	linux/ia64/userent.h		\
 	linux/inet_diag.h		\
+	linux/m68k/arch_regs.c		\
+	linux/m68k/arch_sigreturn.c	\
+	linux/m68k/get_error.c		\
+	linux/m68k/get_scno.c		\
+	linux/m68k/get_syscall_args.c	\
+	linux/m68k/get_syscall_result.c	\
 	linux/m68k/ioctls_arch0.h	\
 	linux/m68k/ioctls_inc0.h	\
+	linux/m68k/print_pc.c		\
 	linux/m68k/syscallent.h		\
 	linux/m68k/userent.h		\
+	linux/metag/arch_regs.c		\
+	linux/metag/get_error.c		\
+	linux/metag/get_scno.c		\
+	linux/metag/get_syscall_args.c	\
 	linux/metag/ioctls_arch0.h	\
 	linux/metag/ioctls_inc0.h	\
+	linux/metag/print_pc.c		\
 	linux/metag/syscallent.h	\
+	linux/microblaze/arch_regs.c	\
+	linux/microblaze/arch_sigreturn.c	\
+	linux/microblaze/get_error.c	\
+	linux/microblaze/get_scno.c	\
+	linux/microblaze/get_syscall_args.c	\
+	linux/microblaze/get_syscall_result.c	\
 	linux/microblaze/ioctls_arch0.h	\
 	linux/microblaze/ioctls_inc0.h	\
+	linux/microblaze/print_pc.c	\
 	linux/microblaze/syscallent.h	\
 	linux/microblaze/userent.h	\
+	linux/mips/arch_getrval2.c	\
+	linux/mips/arch_regs.c		\
 	linux/mips/arch_regs.h		\
+	linux/mips/arch_sigreturn.c	\
 	linux/mips/errnoent.h		\
 	linux/mips/genstub.sh		\
+	linux/mips/get_error.c		\
+	linux/mips/get_scno.c		\
+	linux/mips/get_syscall_args.c	\
 	linux/mips/ioctls_arch0.h	\
 	linux/mips/ioctls_inc0.h	\
+	linux/mips/print_pc.c		\
 	linux/mips/signalent.h		\
 	linux/mips/syscallent-compat.h	\
 	linux/mips/syscallent-n32.h	\
@@ -243,93 +341,145 @@
 	linux/mips/syscallent.h		\
 	linux/mips/userent.h		\
 	linux/mtd-abi.h			\
+	linux/or1k/arch_regs.c		\
+	linux/or1k/get_error.c		\
+	linux/or1k/get_scno.c		\
+	linux/or1k/get_syscall_args.c	\
 	linux/or1k/ioctls_arch0.h	\
 	linux/or1k/ioctls_inc0.h	\
+	linux/or1k/print_pc.c		\
 	linux/or1k/syscallent.h		\
 	linux/or1k/userent.h		\
 	linux/personality.h		\
+	linux/powerpc/arch_regs.c	\
 	linux/powerpc/arch_regs.h	\
+	linux/powerpc/arch_sigreturn.c	\
 	linux/powerpc/errnoent.h	\
+	linux/powerpc/get_error.c	\
+	linux/powerpc/get_scno.c	\
+	linux/powerpc/get_syscall_args.c	\
+	linux/powerpc/getregs_old.c	\
 	linux/powerpc/ioctls_arch0.h	\
 	linux/powerpc/ioctls_inc0.h	\
+	linux/powerpc/print_pc.c	\
 	linux/powerpc/syscallent.h	\
 	linux/powerpc/userent.h		\
+	linux/powerpc64/arch_regs.c	\
 	linux/powerpc64/arch_regs.h	\
+	linux/powerpc64/arch_sigreturn.c	\
 	linux/powerpc64/errnoent.h	\
 	linux/powerpc64/errnoent1.h	\
+	linux/powerpc64/get_error.c	\
+	linux/powerpc64/get_scno.c	\
+	linux/powerpc64/get_syscall_args.c	\
+	linux/powerpc64/getregs_old.c	\
 	linux/powerpc64/ioctls_arch0.h	\
 	linux/powerpc64/ioctls_arch1.h	\
 	linux/powerpc64/ioctls_inc0.h	\
 	linux/powerpc64/ioctls_inc1.h	\
+	linux/powerpc64/print_pc.c	\
 	linux/powerpc64/signalent1.h	\
 	linux/powerpc64/syscallent.h	\
 	linux/powerpc64/syscallent1.h	\
 	linux/powerpc64/userent.h	\
 	linux/ptp_clock.h		\
+	linux/s390/arch_regs.c		\
 	linux/s390/arch_regs.h		\
+	linux/s390/arch_sigreturn.c	\
+	linux/s390/get_error.c		\
+	linux/s390/get_scno.c		\
+	linux/s390/get_syscall_args.c	\
 	linux/s390/ioctls_arch0.h	\
 	linux/s390/ioctls_inc0.h	\
+	linux/s390/print_pc.c		\
 	linux/s390/syscallent.h		\
 	linux/s390/userent.h		\
 	linux/s390/userent0.h		\
 	linux/s390/userent1.h		\
+	linux/s390x/arch_regs.c		\
 	linux/s390x/arch_regs.h		\
+	linux/s390x/arch_sigreturn.c	\
+	linux/s390x/get_error.c		\
+	linux/s390x/get_scno.c		\
+	linux/s390x/get_syscall_args.c	\
 	linux/s390x/ioctls_arch0.h	\
 	linux/s390x/ioctls_inc0.h	\
+	linux/s390x/print_pc.c		\
 	linux/s390x/syscallent.h	\
 	linux/s390x/userent.h		\
+	linux/sh/arch_getrval2.c	\
+	linux/sh/arch_regs.c		\
+	linux/sh/get_error.c		\
+	linux/sh/get_scno.c		\
+	linux/sh/get_syscall_args.c	\
+	linux/sh/get_syscall_result.c	\
 	linux/sh/ioctls_arch0.h		\
 	linux/sh/ioctls_inc0.h		\
+	linux/sh/print_pc.c		\
 	linux/sh/syscallent.h		\
 	linux/sh/userent.h		\
 	linux/sh/userent0.h		\
+	linux/sh64/arch_regs.c		\
 	linux/sh64/arch_regs.h		\
+	linux/sh64/get_error.c		\
+	linux/sh64/get_scno.c		\
+	linux/sh64/get_syscall_args.c	\
+	linux/sh64/get_syscall_result.c	\
 	linux/sh64/ioctls_arch0.h	\
 	linux/sh64/ioctls_inc0.h	\
+	linux/sh64/print_pc.c		\
 	linux/sh64/syscallent.h		\
 	linux/sh64/userent.h		\
 	linux/signalent.h		\
 	linux/sock_diag.h		\
+	linux/sparc/arch_getrval2.c	\
+	linux/sparc/arch_regs.c		\
 	linux/sparc/arch_regs.h		\
-	linux/sparc/dummy2.h		\
+	linux/sparc/arch_sigreturn.c	\
 	linux/sparc/errnoent.h		\
-	linux/sparc/errnoent1.h		\
 	linux/sparc/gen.pl		\
-	linux/sparc/ioctlent1.h		\
+	linux/sparc/get_error.c		\
+	linux/sparc/get_scno.c		\
+	linux/sparc/get_syscall_args.c	\
 	linux/sparc/ioctls_arch0.h	\
 	linux/sparc/ioctls_inc0.h	\
+	linux/sparc/print_pc.c		\
 	linux/sparc/signalent.h		\
-	linux/sparc/signalent1.h	\
-	linux/sparc/syscall1.h		\
 	linux/sparc/syscallent.h	\
-	linux/sparc/syscallent1.h	\
 	linux/sparc/userent.h		\
+	linux/sparc64/arch_getrval2.c	\
+	linux/sparc64/arch_regs.c	\
 	linux/sparc64/arch_regs.h	\
-	linux/sparc64/dummy2.h		\
+	linux/sparc64/arch_sigreturn.c	\
 	linux/sparc64/errnoent.h	\
 	linux/sparc64/errnoent1.h	\
-	linux/sparc64/errnoent2.h	\
-	linux/sparc64/ioctlent1.h	\
+	linux/sparc64/get_error.c	\
+	linux/sparc64/get_scno.c	\
+	linux/sparc64/get_syscall_args.c\
 	linux/sparc64/ioctls_arch0.h	\
-	linux/sparc64/ioctls_arch2.h	\
+	linux/sparc64/ioctls_arch1.h	\
 	linux/sparc64/ioctls_inc0.h	\
-	linux/sparc64/ioctls_inc2.h	\
+	linux/sparc64/ioctls_inc1.h	\
+	linux/sparc64/print_pc.c	\
 	linux/sparc64/signalent.h	\
 	linux/sparc64/signalent1.h	\
-	linux/sparc64/signalent2.h	\
-	linux/sparc64/syscall1.h	\
 	linux/sparc64/syscallent.h	\
 	linux/sparc64/syscallent1.h	\
-	linux/sparc64/syscallent2.h	\
 	linux/sparc64/userent.h		\
 	linux/subcall.h			\
 	linux/syscall.h			\
+	linux/tile/arch_regs.c		\
 	linux/tile/arch_regs.h		\
+	linux/tile/arch_sigreturn.c	\
 	linux/tile/errnoent1.h		\
+	linux/tile/get_error.c		\
+	linux/tile/get_scno.c		\
+	linux/tile/get_syscall_args.c	\
 	linux/tile/ioctls_arch0.h	\
 	linux/tile/ioctls_arch1.h	\
 	linux/tile/ioctls_inc0.h	\
 	linux/tile/ioctls_inc1.h	\
+	linux/tile/print_pc.c		\
 	linux/tile/signalent1.h		\
 	linux/tile/syscallent.h		\
 	linux/tile/syscallent1.h	\
@@ -338,34 +488,53 @@
 	linux/unix_diag.h		\
 	linux/userent.h			\
 	linux/userent0.h		\
+	linux/x32/arch_regs.c		\
 	linux/x32/arch_regs.h		\
+	linux/x32/arch_sigreturn.c	\
 	linux/x32/errnoent1.h		\
+	linux/x32/get_error.c		\
+	linux/x32/get_scno.c		\
+	linux/x32/get_syscall_args.c	\
 	linux/x32/ioctls_arch0.h	\
 	linux/x32/ioctls_arch1.h	\
 	linux/x32/ioctls_inc0.h		\
 	linux/x32/ioctls_inc1.h		\
+	linux/x32/print_pc.c		\
 	linux/x32/signalent1.h		\
 	linux/x32/syscallent.h		\
 	linux/x32/syscallent1.h		\
 	linux/x32/userent.h		\
+	linux/x86_64/arch_regs.c	\
 	linux/x86_64/arch_regs.h	\
+	linux/x86_64/arch_sigreturn.c	\
 	linux/x86_64/errnoent1.h	\
 	linux/x86_64/errnoent2.h	\
 	linux/x86_64/gentab.pl		\
+	linux/x86_64/get_error.c	\
+	linux/x86_64/get_scno.c		\
+	linux/x86_64/get_syscall_args.c	\
+	linux/x86_64/getregs_old.c	\
 	linux/x86_64/ioctls_arch0.h	\
 	linux/x86_64/ioctls_arch1.h	\
 	linux/x86_64/ioctls_arch2.h	\
 	linux/x86_64/ioctls_inc0.h	\
 	linux/x86_64/ioctls_inc1.h	\
 	linux/x86_64/ioctls_inc2.h	\
+	linux/x86_64/print_pc.c		\
 	linux/x86_64/signalent1.h	\
 	linux/x86_64/signalent2.h	\
 	linux/x86_64/syscallent.h	\
 	linux/x86_64/syscallent1.h	\
 	linux/x86_64/syscallent2.h	\
 	linux/x86_64/userent.h		\
+	linux/xtensa/arch_regs.c	\
+	linux/xtensa/get_error.c	\
+	linux/xtensa/get_scno.c		\
+	linux/xtensa/get_syscall_args.c	\
+	linux/xtensa/get_syscall_result.c	\
 	linux/xtensa/ioctls_arch0.h	\
 	linux/xtensa/ioctls_inc0.h	\
+	linux/xtensa/print_pc.c		\
 	linux/xtensa/syscallent.h	\
 	linux/xtensa/userent.h		\
 	maint/ioctls_gen.sh		\
diff --git a/capability.c b/capability.c
index bbd5544..26d9c66 100644
--- a/capability.c
+++ b/capability.c
@@ -103,7 +103,7 @@
 	else
 		len = 1;
 
-	if (umoven(tcp, addr, len * sizeof(data[0]), (char *) data) < 0) {
+	if (umoven(tcp, addr, len * sizeof(data[0]), data) < 0) {
 		tprintf("%#lx", addr);
 		return;
 	}
diff --git a/configure.ac b/configure.ac
index e73958c..d829e18 100644
--- a/configure.ac
+++ b/configure.ac
@@ -228,6 +228,7 @@
 	fputs_unlocked
 	if_indextoname
 	inet_ntop
+	pipe2
 	prctl
 	preadv
 	process_vm_readv
diff --git a/defs.h b/defs.h
index dad4fe8..34f1603 100644
--- a/defs.h
+++ b/defs.h
@@ -67,8 +67,46 @@
 extern char *stpcpy(char *dst, const char *src);
 #endif
 
-#if !defined __GNUC__
-# define __attribute__(x) /*nothing*/
+#if defined __GNUC__ && defined __GNUC_MINOR__
+# define GNUC_PREREQ(maj, min)	\
+	((__GNUC__ << 16) + __GNUC_MINOR__ >= ((maj) << 16) + (min))
+#else
+# define __attribute__(x)	/* empty */
+# define GNUC_PREREQ(maj, min)	0
+#endif
+
+#if GNUC_PREREQ(2, 5)
+# define ATTRIBUTE_NORETURN	__attribute__((__noreturn__))
+#else
+# define ATTRIBUTE_NORETURN	/* empty */
+#endif
+
+#if GNUC_PREREQ(2, 7)
+# define ATTRIBUTE_FORMAT(args)	__attribute__((__format__ args))
+# define ATTRIBUTE_ALIGNED(arg)	__attribute__((__aligned__(arg)))
+# define ATTRIBUTE_PACKED	__attribute__((__packed__))
+#else
+# define ATTRIBUTE_FORMAT(args)	/* empty */
+# define ATTRIBUTE_ALIGNED(arg)	/* empty */
+# define ATTRIBUTE_PACKED	/* empty */
+#endif
+
+#if GNUC_PREREQ(3, 0)
+# define ATTRIBUTE_MALLOC	__attribute__((__malloc__))
+#else
+# define ATTRIBUTE_MALLOC	/* empty */
+#endif
+
+#if GNUC_PREREQ(3, 1)
+# define ATTRIBUTE_NOINLINE	__attribute__((__noinline__))
+#else
+# define ATTRIBUTE_NOINLINE	/* empty */
+#endif
+
+#if GNUC_PREREQ(4, 3)
+# define ATTRIBUTE_ALLOC_SIZE(args)	__attribute__((__alloc_size__ args))
+#else
+# define ATTRIBUTE_ALLOC_SIZE(args)	/* empty */
 #endif
 
 #ifndef offsetof
@@ -152,14 +190,11 @@
 
 #if defined(SPARC) || defined(SPARC64)
 # define PERSONALITY0_WORDSIZE 4
-# define PERSONALITY1_WORDSIZE 4
 # if defined(SPARC64)
-#  define SUPPORTED_PERSONALITIES 3
-#  define PERSONALITY2_WORDSIZE 8
-# else
 #  define SUPPORTED_PERSONALITIES 2
-# endif /* SPARC64 */
-#endif /* SPARC[64] */
+#  define PERSONALITY1_WORDSIZE 8
+# endif
+#endif
 
 #ifdef X86_64
 # define SUPPORTED_PERSONALITIES 3
@@ -243,11 +278,10 @@
 	FILE *outf;		/* Output file for this process */
 	const char *auxstr;	/* Auxiliary info from syscall (see RVAL_STR) */
 	const struct_sysent *s_ent; /* sysent[scno] or dummy struct for bad scno */
+	const struct_sysent *s_prev_ent; /* for "resuming interrupted SYSCALL" msg */
 	struct timeval stime;	/* System time usage as of last process wait */
 	struct timeval dtime;	/* Delta for system time usage */
 	struct timeval etime;	/* Syscall entry time */
-				/* Support for tracing forked processes: */
-	long inst[2];		/* Saved clone args (badly named) */
 
 #ifdef USE_LIBUNWIND
 	struct UPT_info* libunwind_ui;
@@ -392,11 +426,13 @@
 
 enum bitness_t { BITNESS_CURRENT = 0, BITNESS_32 };
 
-void error_msg(const char *fmt, ...) __attribute__ ((format(printf, 1, 2)));
-void perror_msg(const char *fmt, ...) __attribute__ ((format(printf, 1, 2)));
-void error_msg_and_die(const char *fmt, ...) __attribute__ ((noreturn, format(printf, 1, 2)));
-void perror_msg_and_die(const char *fmt, ...) __attribute__ ((noreturn, format(printf, 1, 2)));
-void die_out_of_memory(void) __attribute__ ((noreturn));
+void error_msg(const char *fmt, ...) ATTRIBUTE_FORMAT((printf, 1, 2));
+void perror_msg(const char *fmt, ...) ATTRIBUTE_FORMAT((printf, 1, 2));
+void error_msg_and_die(const char *fmt, ...)
+	ATTRIBUTE_FORMAT((printf, 1, 2)) ATTRIBUTE_NORETURN;
+void perror_msg_and_die(const char *fmt, ...)
+	ATTRIBUTE_FORMAT((printf, 1, 2)) ATTRIBUTE_NORETURN;
+void die_out_of_memory(void) ATTRIBUTE_NORETURN;
 
 #if USE_CUSTOM_PRINTF
 /*
@@ -418,14 +454,20 @@
 
 extern void clear_regs(void);
 extern void get_regs(pid_t pid);
+extern int get_scno(struct tcb *tcp);
 
-extern int umoven(struct tcb *, long, unsigned int, char *);
+extern int umoven(struct tcb *, long, unsigned int, void *);
 #define umove(pid, addr, objp)	\
-	umoven((pid), (addr), sizeof(*(objp)), (char *) (objp))
+	umoven((pid), (addr), sizeof(*(objp)), (void *) (objp))
 extern int umovestr(struct tcb *, long, unsigned int, char *);
 extern int upeek(int pid, long, long *);
-#if defined(SPARC) || defined(SPARC64) || defined(IA64) || defined(SH)
+
+#if defined ALPHA || defined IA64 || defined MIPS \
+ || defined SH || defined SPARC || defined SPARC64
+# define HAVE_GETRVAL2
 extern long getrval2(struct tcb *);
+#else
+# undef HAVE_GETRVAL2
 #endif
 
 extern const char *signame(const int);
@@ -436,6 +478,7 @@
 extern const char *xlookup(const struct xlat *, const unsigned int);
 extern const char *xlat_search(const struct xlat *, const size_t, const unsigned int);
 
+extern unsigned long get_pagesize(void);
 extern int string_to_uint(const char *str);
 extern int next_set_bit(const void *bit_array, unsigned cur_bit, unsigned size_bits);
 
@@ -456,7 +499,7 @@
 #endif
 extern int getllval(struct tcb *, unsigned long long *, int);
 extern int printllval(struct tcb *, const char *, int)
-	__attribute__ ((format (printf, 2, 0)));
+	ATTRIBUTE_FORMAT((printf, 2, 0));
 
 extern void printxval(const struct xlat *, const unsigned int, const char *);
 extern int printargs(struct tcb *);
@@ -473,9 +516,9 @@
 extern void dumpstr(struct tcb *, long, int);
 extern void printstr(struct tcb *, long, long);
 extern void printnum_int(struct tcb *, long, const char *)
-	__attribute__ ((format (printf, 3, 0)));
+	ATTRIBUTE_FORMAT((printf, 3, 0));
 extern void printnum_long(struct tcb *, long, const char *)
-	__attribute__ ((format (printf, 3, 0)));
+	ATTRIBUTE_FORMAT((printf, 3, 0));
 extern void printpath(struct tcb *, long);
 extern void printpathn(struct tcb *, long, unsigned int);
 #define TIMESPEC_TEXT_BUFSIZE (sizeof(long)*3 * 2 + sizeof("{%u, %u}"))
@@ -488,7 +531,7 @@
 extern char *sprinttv(char *, struct tcb *, long, enum bitness_t, int special);
 extern void print_timespec(struct tcb *, long);
 extern void sprint_timespec(char *, struct tcb *, long);
-extern void printsiginfo(const siginfo_t *, int);
+extern void printsiginfo(const siginfo_t *, bool);
 extern void printsiginfo_at(struct tcb *tcp, long addr);
 extern void printfd(struct tcb *, int);
 extern bool print_sockaddr_by_inode(const unsigned long, const char *);
@@ -567,7 +610,7 @@
 extern void printleader(struct tcb *);
 extern void line_ended(void);
 extern void tabto(void);
-extern void tprintf(const char *fmt, ...) __attribute__ ((format (printf, 1, 2)));
+extern void tprintf(const char *fmt, ...) ATTRIBUTE_FORMAT((printf, 1, 2));
 extern void tprints(const char *str);
 
 #if SUPPORTED_PERSONALITIES > 1
diff --git a/desc.c b/desc.c
index 24de51d..485c802 100644
--- a/desc.c
+++ b/desc.c
@@ -353,7 +353,7 @@
 				tprintf(", %#lx", arg);
 				continue;
 			}
-			if (umoven(tcp, arg, fdsize, (char *) fds) < 0) {
+			if (umoven(tcp, arg, fdsize, fds) < 0) {
 				tprints(", [?]");
 				continue;
 			}
@@ -397,7 +397,7 @@
 			int first = 1;
 
 			arg = args[i+1];
-			if (!arg || umoven(tcp, arg, fdsize, (char *) fds) < 0)
+			if (!arg || umoven(tcp, arg, fdsize, fds) < 0)
 				continue;
 			for (j = 0;; j++) {
 				j = next_set_bit(fds, j, nfds);
@@ -445,7 +445,7 @@
 {
 	long args[5];
 
-	if (umoven(tcp, tcp->u_arg[0], sizeof args, (char *) args) < 0) {
+	if (umoven(tcp, tcp->u_arg[0], sizeof args, args) < 0) {
 		tprints("[...]");
 		return 0;
 	}
diff --git a/evdev.c b/evdev.c
index 9a7430d..e06f9c1 100644
--- a/evdev.c
+++ b/evdev.c
@@ -28,6 +28,8 @@
 
 #include "defs.h"
 
+#include <linux/ioctl.h>
+
 #ifdef HAVE_LINUX_INPUT_H
 #include <linux/input.h>
 #include "xlat/evdev_abs.h"
diff --git a/file.c b/file.c
index ae74d5a..9dc7595 100644
--- a/file.c
+++ b/file.c
@@ -305,7 +305,6 @@
  * Linux x86_64 and x32 have unified `struct stat' but their i386 personality
  * needs `struct stat64'.
  * linux/arch/x86/include/uapi/asm/stat.h defines `struct stat64' only for i386.
- * __GNUC__ is needed for the required __attribute__ below.
  *
  * Similarly, aarch64 has a unified `struct stat' but its arm personality
  * needs `struct stat64' (unlike x86, it shouldn't be packed).
@@ -332,7 +331,7 @@
 	unsigned long long	st_ino;
 }
 #  if defined X86_64 || defined X32
-  __attribute__((packed))
+  ATTRIBUTE_PACKED
 #   define STAT64_SIZE	96
 #  else
 #   define STAT64_SIZE	104
diff --git a/io.c b/io.c
index 3626c77..0618509 100644
--- a/io.c
+++ b/io.c
@@ -112,7 +112,7 @@
 			tprints("...");
 			break;
 		}
-		if (umoven(tcp, cur, sizeof_iov, (char *) &iov) < 0) {
+		if (umoven(tcp, cur, sizeof_iov, &iov) < 0) {
 			tprints("?");
 			failed = 1;
 			break;
diff --git a/ioctl.c b/ioctl.c
index 46f8334..c67d048 100644
--- a/ioctl.c
+++ b/ioctl.c
@@ -29,7 +29,7 @@
  */
 
 #include "defs.h"
-#include <asm/ioctl.h>
+#include <linux/ioctl.h>
 #include "xlat/ioctl_dirs.h"
 
 #ifdef HAVE_LINUX_INPUT_H
diff --git a/ioctlsort.c b/ioctlsort.c
index 333556c..9c31691 100644
--- a/ioctlsort.c
+++ b/ioctlsort.c
@@ -33,7 +33,7 @@
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
-#include <asm/ioctl.h>
+#include <linux/ioctl.h>
 
 struct ioctlent {
 	const char *info;
diff --git a/kexec.c b/kexec.c
index e277668..6bec51c 100644
--- a/kexec.c
+++ b/kexec.c
@@ -58,8 +58,7 @@
 	for (i = 0; i < len; ++i) {
 		if (i)
 			tprints(", ");
-		if (umoven(tcp, addr + i * sizeof_seg, sizeof_seg,
-			   (char *) &seg) < 0) {
+		if (umoven(tcp, addr + i * sizeof_seg, sizeof_seg, &seg) < 0) {
 			tprints("?");
 			failed = 1;
 			break;
diff --git a/linux/aarch64/arch_regs.c b/linux/aarch64/arch_regs.c
new file mode 100644
index 0000000..3b9c2f6
--- /dev/null
+++ b/linux/aarch64/arch_regs.c
@@ -0,0 +1,37 @@
+struct arm_pt_regs {
+        int uregs[18];
+};
+#define ARM_cpsr       uregs[16]
+#define ARM_pc         uregs[15]
+#define ARM_lr         uregs[14]
+#define ARM_sp         uregs[13]
+#define ARM_ip         uregs[12]
+#define ARM_fp         uregs[11]
+#define ARM_r10        uregs[10]
+#define ARM_r9         uregs[9]
+#define ARM_r8         uregs[8]
+#define ARM_r7         uregs[7]
+#define ARM_r6         uregs[6]
+#define ARM_r5         uregs[5]
+#define ARM_r4         uregs[4]
+#define ARM_r3         uregs[3]
+#define ARM_r2         uregs[2]
+#define ARM_r1         uregs[1]
+#define ARM_r0         uregs[0]
+#define ARM_ORIG_r0    uregs[17]
+
+static union {
+	struct user_pt_regs aarch64_r;
+	struct arm_pt_regs  arm_r;
+} arm_regs_union;
+#define aarch64_regs arm_regs_union.aarch64_r
+#define arm_regs     arm_regs_union.arm_r
+
+uint64_t *const aarch64_sp_ptr = (uint64_t *) &aarch64_regs.sp;
+uint32_t *const arm_sp_ptr = (uint32_t *) &arm_regs.ARM_sp;
+static struct iovec aarch64_io = {
+	.iov_base = &arm_regs_union
+};
+
+#define ARCH_REGS_FOR_GETREGSET arm_regs_union
+#define ARCH_IOVEC_FOR_GETREGSET aarch64_io
diff --git a/linux/aarch64/arch_sigreturn.c b/linux/aarch64/arch_sigreturn.c
new file mode 100644
index 0000000..f0e29c2
--- /dev/null
+++ b/linux/aarch64/arch_sigreturn.c
@@ -0,0 +1 @@
+#include "arm/arch_sigreturn.c"
diff --git a/linux/aarch64/get_error.c b/linux/aarch64/get_error.c
new file mode 100644
index 0000000..7dd6779
--- /dev/null
+++ b/linux/aarch64/get_error.c
@@ -0,0 +1,10 @@
+if (tcp->currpers == 1) {
+	if (check_errno && is_negated_errno(aarch64_regs.regs[0])) {
+		tcp->u_rval = -1;
+		tcp->u_error = -aarch64_regs.regs[0];
+	} else {
+		tcp->u_rval = aarch64_regs.regs[0];
+	}
+} else {
+#include "arm/get_error.c"
+}
diff --git a/linux/aarch64/get_scno.c b/linux/aarch64/get_scno.c
new file mode 100644
index 0000000..610b38d
--- /dev/null
+++ b/linux/aarch64/get_scno.c
@@ -0,0 +1,14 @@
+switch (aarch64_io.iov_len) {
+	case sizeof(aarch64_regs):
+		/* We are in 64-bit mode */
+		scno = aarch64_regs.regs[8];
+		update_personality(tcp, 1);
+		break;
+	case sizeof(arm_regs):
+		/* We are in 32-bit mode */
+		/* Note: we don't support OABI, unlike 32-bit ARM build */
+		scno = arm_regs.ARM_r7;
+		scno = shuffle_scno(scno);
+		update_personality(tcp, 0);
+		break;
+}
diff --git a/linux/aarch64/get_syscall_args.c b/linux/aarch64/get_syscall_args.c
new file mode 100644
index 0000000..41ce8b4
--- /dev/null
+++ b/linux/aarch64/get_syscall_args.c
@@ -0,0 +1,10 @@
+if (tcp->currpers == 1) {
+	tcp->u_arg[0] = aarch64_regs.regs[0];
+	tcp->u_arg[1] = aarch64_regs.regs[1];
+	tcp->u_arg[2] = aarch64_regs.regs[2];
+	tcp->u_arg[3] = aarch64_regs.regs[3];
+	tcp->u_arg[4] = aarch64_regs.regs[4];
+	tcp->u_arg[5] = aarch64_regs.regs[5];
+} else {
+#include "arm/get_syscall_args.c"
+}
diff --git a/linux/aarch64/print_pc.c b/linux/aarch64/print_pc.c
new file mode 100644
index 0000000..23c0e5c
--- /dev/null
+++ b/linux/aarch64/print_pc.c
@@ -0,0 +1,4 @@
+if (aarch64_io.iov_len == sizeof(arm_regs))
+	tprintf(fmt, (unsigned long) arm_regs.ARM_pc);
+else
+	tprintf(fmt, (unsigned long) aarch64_regs.pc);
diff --git a/linux/alpha/arch_getrval2.c b/linux/alpha/arch_getrval2.c
new file mode 100644
index 0000000..90ee392
--- /dev/null
+++ b/linux/alpha/arch_getrval2.c
@@ -0,0 +1,8 @@
+long
+getrval2(struct tcb *tcp)
+{
+	long r20;
+	if (upeek(tcp->pid, 20, &r20) < 0)
+		return -1;
+	return r20;
+}
diff --git a/linux/alpha/arch_regs.c b/linux/alpha/arch_regs.c
new file mode 100644
index 0000000..e2783ca
--- /dev/null
+++ b/linux/alpha/arch_regs.c
@@ -0,0 +1,2 @@
+static long alpha_r0;
+static long alpha_a3;
diff --git a/linux/alpha/arch_sigreturn.c b/linux/alpha/arch_sigreturn.c
new file mode 100644
index 0000000..278bae1
--- /dev/null
+++ b/linux/alpha/arch_sigreturn.c
@@ -0,0 +1,9 @@
+long addr;
+
+if (upeek(tcp->pid, REG_FP, &addr) < 0)
+	return 0;
+addr += offsetof(struct sigcontext, sc_mask);
+
+tprints("{mask=");
+print_sigset_addr_len(tcp, addr, NSIG / 8);
+tprints("}");
diff --git a/linux/alpha/get_error.c b/linux/alpha/get_error.c
new file mode 100644
index 0000000..5b615a5
--- /dev/null
+++ b/linux/alpha/get_error.c
@@ -0,0 +1,6 @@
+if (check_errno && alpha_a3) {
+	tcp->u_rval = -1;
+	tcp->u_error = alpha_r0;
+} else {
+	tcp->u_rval = alpha_r0;
+}
diff --git a/linux/alpha/get_scno.c b/linux/alpha/get_scno.c
new file mode 100644
index 0000000..4959e15
--- /dev/null
+++ b/linux/alpha/get_scno.c
@@ -0,0 +1,16 @@
+if (upeek(tcp->pid, REG_A3, &alpha_a3) < 0)
+	return -1;
+if (upeek(tcp->pid, REG_R0, &scno) < 0)
+	return -1;
+
+/*
+ * Do some sanity checks to figure out if it's
+ * really a syscall entry
+ */
+if (!SCNO_IN_RANGE(scno)) {
+	if (alpha_a3 == 0 || alpha_a3 == -1) {
+		if (debug_flag)
+			fprintf(stderr, "stray syscall exit: r0 = %ld\n", scno);
+		return 0;
+	}
+}
diff --git a/linux/alpha/get_syscall_args.c b/linux/alpha/get_syscall_args.c
new file mode 100644
index 0000000..7f7d493
--- /dev/null
+++ b/linux/alpha/get_syscall_args.c
@@ -0,0 +1,5 @@
+unsigned int i;
+
+for (i = 0; i < tcp->s_ent->nargs; ++i)
+	if (upeek(tcp->pid, REG_A0+i, &tcp->u_arg[i]) < 0)
+		return -1;
diff --git a/linux/alpha/get_syscall_result.c b/linux/alpha/get_syscall_result.c
new file mode 100644
index 0000000..11e2736
--- /dev/null
+++ b/linux/alpha/get_syscall_result.c
@@ -0,0 +1,4 @@
+if (upeek(tcp->pid, REG_A3, &alpha_a3) < 0)
+	return -1;
+if (upeek(tcp->pid, REG_R0, &alpha_r0) < 0)
+	return -1;
diff --git a/linux/alpha/print_pc.c b/linux/alpha/print_pc.c
new file mode 100644
index 0000000..c0232e5
--- /dev/null
+++ b/linux/alpha/print_pc.c
@@ -0,0 +1,6 @@
+long pc;
+if (upeek(tcp->pid, REG_PC, &pc) < 0) {
+	PRINTBADPC;
+	return;
+}
+tprintf(fmt, pc);
diff --git a/linux/arc/arch_regs.c b/linux/arc/arch_regs.c
new file mode 100644
index 0000000..0d57ae4
--- /dev/null
+++ b/linux/arc/arch_regs.c
@@ -0,0 +1,2 @@
+static struct user_regs_struct arc_regs;
+#define ARCH_REGS_FOR_GETREGSET arc_regs
diff --git a/linux/arc/get_error.c b/linux/arc/get_error.c
new file mode 100644
index 0000000..1741c17
--- /dev/null
+++ b/linux/arc/get_error.c
@@ -0,0 +1,6 @@
+if (check_errno && is_negated_errno(arc_regs.scratch.r0)) {
+	tcp->u_rval = -1;
+	tcp->u_error = -arc_regs.scratch.r0;
+} else {
+	tcp->u_rval = arc_regs.scratch.r0;
+}
diff --git a/linux/arc/get_scno.c b/linux/arc/get_scno.c
new file mode 100644
index 0000000..cc45d46
--- /dev/null
+++ b/linux/arc/get_scno.c
@@ -0,0 +1 @@
+scno = arc_regs.scratch.r8;
diff --git a/linux/arc/get_syscall_args.c b/linux/arc/get_syscall_args.c
new file mode 100644
index 0000000..bb003c8
--- /dev/null
+++ b/linux/arc/get_syscall_args.c
@@ -0,0 +1,5 @@
+long *arc_args = &arc_regs.scratch.r0;
+unsigned int i;
+
+for (i = 0; i < MAX_ARGS; ++i)
+	tcp->u_arg[i] = *arc_args--;
diff --git a/linux/arc/print_pc.c b/linux/arc/print_pc.c
new file mode 100644
index 0000000..f904544
--- /dev/null
+++ b/linux/arc/print_pc.c
@@ -0,0 +1 @@
+tprintf(fmt, arc_regs.efa);
diff --git a/linux/arch_sigreturn.c b/linux/arch_sigreturn.c
new file mode 100644
index 0000000..80ec984
--- /dev/null
+++ b/linux/arch_sigreturn.c
@@ -0,0 +1 @@
+#warning sigreturn/rt_sigreturn signal mask decoding is not implemented for this architecture
diff --git a/linux/arm/arch_regs.c b/linux/arm/arch_regs.c
new file mode 100644
index 0000000..ca1fb6d
--- /dev/null
+++ b/linux/arm/arch_regs.c
@@ -0,0 +1,4 @@
+static struct pt_regs arm_regs;
+long *const arm_sp_ptr = &arm_regs.ARM_sp;
+
+#define ARCH_REGS_FOR_GETREGS arm_regs
diff --git a/linux/arm/arch_sigreturn.c b/linux/arm/arch_sigreturn.c
new file mode 100644
index 0000000..046e19a
--- /dev/null
+++ b/linux/arm/arch_sigreturn.c
@@ -0,0 +1,15 @@
+#define SIZEOF_STRUCT_SIGINFO 128
+#define SIZEOF_STRUCT_SIGCONTEXT (21 * 4)
+#define OFFSETOF_STRUCT_UCONTEXT_UC_SIGMASK (5 * 4 + SIZEOF_STRUCT_SIGCONTEXT)
+
+const long addr =
+#ifdef AARCH64
+	current_personality == 1 ?
+		(*aarch64_sp_ptr + SIZEOF_STRUCT_SIGINFO +
+		 offsetof(struct ucontext, uc_sigmask)) :
+#endif
+		(*arm_sp_ptr +
+		 OFFSETOF_STRUCT_UCONTEXT_UC_SIGMASK);
+tprints("{mask=");
+print_sigset_addr_len(tcp, addr, NSIG / 8);
+tprints("}");
diff --git a/linux/arm/get_error.c b/linux/arm/get_error.c
new file mode 100644
index 0000000..d2ae09b
--- /dev/null
+++ b/linux/arm/get_error.c
@@ -0,0 +1,6 @@
+if (check_errno && is_negated_errno(arm_regs.ARM_r0)) {
+	tcp->u_rval = -1;
+	tcp->u_error = -arm_regs.ARM_r0;
+} else {
+	tcp->u_rval = arm_regs.ARM_r0;
+}
diff --git a/linux/arm/get_scno.c b/linux/arm/get_scno.c
new file mode 100644
index 0000000..f9dcd65
--- /dev/null
+++ b/linux/arm/get_scno.c
@@ -0,0 +1,46 @@
+/* Note: we support only 32-bit CPUs, not 26-bit */
+
+#if !defined(__ARM_EABI__) || ENABLE_ARM_OABI
+if (arm_regs.ARM_cpsr & 0x20) {
+	/* Thumb mode */
+	goto scno_in_r7;
+}
+/* ARM mode */
+/* Check EABI/OABI by examining SVC insn's low 24 bits */
+errno = 0;
+scno = ptrace(PTRACE_PEEKTEXT, tcp->pid, (void *)(arm_regs.ARM_pc - 4), NULL);
+if (errno)
+	return -1;
+/* EABI syscall convention? */
+if ((unsigned long) scno != 0xef000000) {
+	/* No, it's OABI */
+	if ((scno & 0x0ff00000) != 0x0f900000) {
+		fprintf(stderr, "pid %d unknown syscall trap 0x%08lx\n",
+			tcp->pid, scno);
+		return -1;
+	}
+	/* Fixup the syscall number */
+	scno &= 0x000fffff;
+} else {
+scno_in_r7:
+	scno = arm_regs.ARM_r7;
+}
+#else /* __ARM_EABI__ || !ENABLE_ARM_OABI */
+
+scno = arm_regs.ARM_r7;
+
+#endif
+
+scno = shuffle_scno(scno);
+
+/*
+ * Do some sanity checks to figure out
+ * whether it's really a syscall entry.
+ */
+if (arm_regs.ARM_ip && !SCNO_IN_RANGE(scno)) {
+	if (debug_flag)
+		fprintf(stderr,
+			"pid %d stray syscall exit: ARM_ip = %ld, scno = %ld\n",
+			tcp->pid, arm_regs.ARM_ip, shuffle_scno(scno));
+	return 0;
+}
diff --git a/linux/arm/get_syscall_args.c b/linux/arm/get_syscall_args.c
new file mode 100644
index 0000000..1bd4faf
--- /dev/null
+++ b/linux/arm/get_syscall_args.c
@@ -0,0 +1,6 @@
+tcp->u_arg[0] = arm_regs.uregs[0];
+tcp->u_arg[1] = arm_regs.uregs[1];
+tcp->u_arg[2] = arm_regs.uregs[2];
+tcp->u_arg[3] = arm_regs.uregs[3];
+tcp->u_arg[4] = arm_regs.uregs[4];
+tcp->u_arg[5] = arm_regs.uregs[5];
diff --git a/linux/arm/print_pc.c b/linux/arm/print_pc.c
new file mode 100644
index 0000000..b9d9622
--- /dev/null
+++ b/linux/arm/print_pc.c
@@ -0,0 +1 @@
+tprintf(fmt, arm_regs.ARM_pc);
diff --git a/linux/avr32/arch_regs.c b/linux/avr32/arch_regs.c
new file mode 100644
index 0000000..aab0338
--- /dev/null
+++ b/linux/avr32/arch_regs.c
@@ -0,0 +1,2 @@
+static struct pt_regs avr32_regs;
+#define ARCH_REGS_FOR_GETREGS avr32_regs
diff --git a/linux/avr32/get_error.c b/linux/avr32/get_error.c
new file mode 100644
index 0000000..ef44584
--- /dev/null
+++ b/linux/avr32/get_error.c
@@ -0,0 +1,6 @@
+if (check_errno && is_negated_errno(avr32_regs.r12)) {
+	tcp->u_rval = -1;
+	tcp->u_error = -avr32_regs.r12;
+} else {
+	tcp->u_rval = avr32_regs.r12;
+}
diff --git a/linux/avr32/get_scno.c b/linux/avr32/get_scno.c
new file mode 100644
index 0000000..0142329
--- /dev/null
+++ b/linux/avr32/get_scno.c
@@ -0,0 +1 @@
+scno = avr32_regs.r8;
diff --git a/linux/avr32/get_syscall_args.c b/linux/avr32/get_syscall_args.c
new file mode 100644
index 0000000..2e3cd3b
--- /dev/null
+++ b/linux/avr32/get_syscall_args.c
@@ -0,0 +1,6 @@
+tcp->u_arg[0] = avr32_regs.r12;
+tcp->u_arg[1] = avr32_regs.r11;
+tcp->u_arg[2] = avr32_regs.r10;
+tcp->u_arg[3] = avr32_regs.r9;
+tcp->u_arg[4] = avr32_regs.r5;
+tcp->u_arg[5] = avr32_regs.r3;
diff --git a/linux/avr32/print_pc.c b/linux/avr32/print_pc.c
new file mode 100644
index 0000000..ca293e6
--- /dev/null
+++ b/linux/avr32/print_pc.c
@@ -0,0 +1 @@
+tprintf(fmt, avr32_regs.pc);
diff --git a/linux/bfin/arch_regs.c b/linux/bfin/arch_regs.c
new file mode 100644
index 0000000..f6f4204
--- /dev/null
+++ b/linux/bfin/arch_regs.c
@@ -0,0 +1 @@
+static long bfin_r0;
diff --git a/linux/bfin/get_error.c b/linux/bfin/get_error.c
new file mode 100644
index 0000000..d7ff247
--- /dev/null
+++ b/linux/bfin/get_error.c
@@ -0,0 +1,6 @@
+if (check_errno && is_negated_errno(bfin_r0)) {
+	tcp->u_rval = -1;
+	tcp->u_error = -bfin_r0;
+} else {
+	tcp->u_rval = bfin_r0;
+}
diff --git a/linux/bfin/get_scno.c b/linux/bfin/get_scno.c
new file mode 100644
index 0000000..dfdb0a7
--- /dev/null
+++ b/linux/bfin/get_scno.c
@@ -0,0 +1,2 @@
+if (upeek(tcp->pid, PT_ORIG_P0, &scno))
+	return -1;
diff --git a/linux/bfin/get_syscall_args.c b/linux/bfin/get_syscall_args.c
new file mode 100644
index 0000000..ac6e6cd
--- /dev/null
+++ b/linux/bfin/get_syscall_args.c
@@ -0,0 +1,6 @@
+static const int argreg[MAX_ARGS] = { PT_R0, PT_R1, PT_R2, PT_R3, PT_R4, PT_R5 };
+unsigned int i;
+
+for (i = 0; i < tcp->s_ent->nargs; ++i)
+	if (upeek(tcp->pid, argreg[i], &tcp->u_arg[i]) < 0)
+		return -1;
diff --git a/linux/bfin/get_syscall_result.c b/linux/bfin/get_syscall_result.c
new file mode 100644
index 0000000..c9d94d4
--- /dev/null
+++ b/linux/bfin/get_syscall_result.c
@@ -0,0 +1,2 @@
+if (upeek(tcp->pid, PT_R0, &bfin_r0) < 0)
+	return -1;
diff --git a/linux/bfin/print_pc.c b/linux/bfin/print_pc.c
new file mode 100644
index 0000000..b1eef14
--- /dev/null
+++ b/linux/bfin/print_pc.c
@@ -0,0 +1,6 @@
+long pc;
+if (upeek(tcp->pid, PT_PC, &pc) < 0) {
+	PRINTBADPC;
+	return;
+}
+tprintf(fmt, pc);
diff --git a/linux/crisv10/arch_regs.c b/linux/crisv10/arch_regs.c
new file mode 100644
index 0000000..573f593
--- /dev/null
+++ b/linux/crisv10/arch_regs.c
@@ -0,0 +1 @@
+static long cris_r10;
diff --git a/linux/crisv10/arch_sigreturn.c b/linux/crisv10/arch_sigreturn.c
new file mode 100644
index 0000000..b9e6a24
--- /dev/null
+++ b/linux/crisv10/arch_sigreturn.c
@@ -0,0 +1,11 @@
+long regs[PT_MAX + 1];
+
+if (ptrace(PTRACE_GETREGS, tcp->pid, NULL, (long)regs) < 0) {
+	perror_msg("sigreturn: PTRACE_GETREGS");
+	return 0;
+}
+const long addr = regs[PT_USP] + offsetof(struct sigcontext, oldmask);
+
+tprints("{mask=");
+print_sigset_addr_len(tcp, addr, NSIG / 8);
+tprints("}");
diff --git a/linux/crisv10/get_error.c b/linux/crisv10/get_error.c
new file mode 100644
index 0000000..3f947ae
--- /dev/null
+++ b/linux/crisv10/get_error.c
@@ -0,0 +1,6 @@
+if (check_errno && is_negated_errno(cris_r10)) {
+	tcp->u_rval = -1;
+	tcp->u_error = -cris_r10;
+} else {
+	tcp->u_rval = cris_r10;
+}
diff --git a/linux/crisv10/get_scno.c b/linux/crisv10/get_scno.c
new file mode 100644
index 0000000..5bbbe8b
--- /dev/null
+++ b/linux/crisv10/get_scno.c
@@ -0,0 +1,2 @@
+if (upeek(tcp->pid, 4*PT_R9, &scno) < 0)
+	return -1;
diff --git a/linux/crisv10/get_syscall_args.c b/linux/crisv10/get_syscall_args.c
new file mode 100644
index 0000000..66b5ac7
--- /dev/null
+++ b/linux/crisv10/get_syscall_args.c
@@ -0,0 +1,9 @@
+static const int crisregs[MAX_ARGS] = {
+	4*PT_ORIG_R10, 4*PT_R11, 4*PT_R12,
+	4*PT_R13     , 4*PT_MOF, 4*PT_SRP
+};
+unsigned int i;
+
+for (i = 0; i < tcp->s_ent->nargs; ++i)
+	if (upeek(tcp->pid, crisregs[i], &tcp->u_arg[i]) < 0)
+		return -1;
diff --git a/linux/crisv10/get_syscall_result.c b/linux/crisv10/get_syscall_result.c
new file mode 100644
index 0000000..53b087a
--- /dev/null
+++ b/linux/crisv10/get_syscall_result.c
@@ -0,0 +1,2 @@
+if (upeek(tcp->pid, 4*PT_R10, &cris_r10) < 0)
+	return -1;
diff --git a/linux/crisv10/print_pc.c b/linux/crisv10/print_pc.c
new file mode 100644
index 0000000..cc76216
--- /dev/null
+++ b/linux/crisv10/print_pc.c
@@ -0,0 +1,6 @@
+long pc;
+if (upeek(tcp->pid, 4*PT_IRP, &pc) < 0) {
+	PRINTBADPC;
+	return;
+}
+tprintf(fmt, pc);
diff --git a/linux/crisv32/arch_regs.c b/linux/crisv32/arch_regs.c
new file mode 100644
index 0000000..a088e17
--- /dev/null
+++ b/linux/crisv32/arch_regs.c
@@ -0,0 +1 @@
+#include "crisv10/arch_regs.c"
diff --git a/linux/crisv32/arch_sigreturn.c b/linux/crisv32/arch_sigreturn.c
new file mode 100644
index 0000000..6c0fc03
--- /dev/null
+++ b/linux/crisv32/arch_sigreturn.c
@@ -0,0 +1 @@
+#include "crisv10/arch_sigreturn.c"
diff --git a/linux/crisv32/get_error.c b/linux/crisv32/get_error.c
new file mode 100644
index 0000000..f7bb1e0
--- /dev/null
+++ b/linux/crisv32/get_error.c
@@ -0,0 +1 @@
+#include "crisv10/get_error.c"
diff --git a/linux/crisv32/get_scno.c b/linux/crisv32/get_scno.c
new file mode 100644
index 0000000..edfd60f
--- /dev/null
+++ b/linux/crisv32/get_scno.c
@@ -0,0 +1 @@
+#include "crisv10/get_scno.c"
diff --git a/linux/crisv32/get_syscall_args.c b/linux/crisv32/get_syscall_args.c
new file mode 100644
index 0000000..4d98465
--- /dev/null
+++ b/linux/crisv32/get_syscall_args.c
@@ -0,0 +1 @@
+#include "crisv10/get_syscall_args.c"
diff --git a/linux/crisv32/get_syscall_result.c b/linux/crisv32/get_syscall_result.c
new file mode 100644
index 0000000..ebefdb2
--- /dev/null
+++ b/linux/crisv32/get_syscall_result.c
@@ -0,0 +1 @@
+#include "crisv10/get_syscall_result.c"
diff --git a/linux/crisv32/print_pc.c b/linux/crisv32/print_pc.c
new file mode 100644
index 0000000..b4af692
--- /dev/null
+++ b/linux/crisv32/print_pc.c
@@ -0,0 +1,6 @@
+long pc;
+if (upeek(tcp->pid, 4*PT_ERP, &pc) < 0) {
+	PRINTBADPC;
+	return;
+}
+tprintf(fmt, pc);
diff --git a/linux/hppa/arch_regs.c b/linux/hppa/arch_regs.c
new file mode 100644
index 0000000..56d1ee3
--- /dev/null
+++ b/linux/hppa/arch_regs.c
@@ -0,0 +1 @@
+static long hppa_r28;
diff --git a/linux/hppa/get_error.c b/linux/hppa/get_error.c
new file mode 100644
index 0000000..901aa54
--- /dev/null
+++ b/linux/hppa/get_error.c
@@ -0,0 +1,6 @@
+if (check_errno && is_negated_errno(hppa_r28)) {
+	tcp->u_rval = -1;
+	tcp->u_error = -hppa_r28;
+} else {
+	tcp->u_rval = hppa_r28;
+}
diff --git a/linux/hppa/get_scno.c b/linux/hppa/get_scno.c
new file mode 100644
index 0000000..0dc1a46
--- /dev/null
+++ b/linux/hppa/get_scno.c
@@ -0,0 +1,2 @@
+if (upeek(tcp->pid, PT_GR20, &scno) < 0)
+	return -1;
diff --git a/linux/hppa/get_syscall_args.c b/linux/hppa/get_syscall_args.c
new file mode 100644
index 0000000..117b68b
--- /dev/null
+++ b/linux/hppa/get_syscall_args.c
@@ -0,0 +1,5 @@
+unsigned int i;
+
+for (i = 0; i < tcp->s_ent->nargs; ++i)
+	if (upeek(tcp->pid, PT_GR26-4*i, &tcp->u_arg[i]) < 0)
+		return -1;
diff --git a/linux/hppa/get_syscall_result.c b/linux/hppa/get_syscall_result.c
new file mode 100644
index 0000000..d929b9f
--- /dev/null
+++ b/linux/hppa/get_syscall_result.c
@@ -0,0 +1,2 @@
+if (upeek(tcp->pid, PT_GR28, &hppa_r28) < 0)
+	return -1;
diff --git a/linux/hppa/print_pc.c b/linux/hppa/print_pc.c
new file mode 100644
index 0000000..7656346
--- /dev/null
+++ b/linux/hppa/print_pc.c
@@ -0,0 +1,6 @@
+long pc;
+if (upeek(tcp->pid, PT_IAOQ0, &pc) < 0) {
+	PRINTBADPC;
+	return;
+}
+tprintf(fmt, pc);
diff --git a/linux/i386/arch_regs.c b/linux/i386/arch_regs.c
new file mode 100644
index 0000000..15b5615
--- /dev/null
+++ b/linux/i386/arch_regs.c
@@ -0,0 +1,4 @@
+static struct user_regs_struct i386_regs;
+long *const i386_esp_ptr = &i386_regs.esp;
+
+#define ARCH_REGS_FOR_GETREGS i386_regs
diff --git a/linux/i386/arch_sigreturn.c b/linux/i386/arch_sigreturn.c
new file mode 100644
index 0000000..e726bf1
--- /dev/null
+++ b/linux/i386/arch_sigreturn.c
@@ -0,0 +1,20 @@
+/*
+ * On i386, sigcontext is followed on stack by struct fpstate
+ * and after it an additional u32 extramask which holds
+ * upper half of the mask.
+ */
+struct {
+	uint32_t struct_sigcontext_padding1[20];
+	uint32_t oldmask;
+	uint32_t struct_sigcontext_padding2;
+	uint32_t struct_fpstate_padding[156];
+	uint32_t extramask;
+} frame;
+
+if (umove(tcp, *i386_esp_ptr, &frame) < 0) {
+	tprintf("{mask=%#lx}", (unsigned long) *i386_esp_ptr);
+} else {
+	uint32_t mask[2] = { frame.oldmask, frame.extramask };
+	tprintsigmask_addr("{mask=", mask);
+	tprints("}");
+}
diff --git a/linux/i386/get_error.c b/linux/i386/get_error.c
new file mode 100644
index 0000000..465118b
--- /dev/null
+++ b/linux/i386/get_error.c
@@ -0,0 +1,6 @@
+if (check_errno && is_negated_errno(i386_regs.eax)) {
+	tcp->u_rval = -1;
+	tcp->u_error = -i386_regs.eax;
+} else {
+	tcp->u_rval = i386_regs.eax;
+}
diff --git a/linux/i386/get_scno.c b/linux/i386/get_scno.c
new file mode 100644
index 0000000..fa22fa6
--- /dev/null
+++ b/linux/i386/get_scno.c
@@ -0,0 +1 @@
+scno = i386_regs.orig_eax;
diff --git a/linux/i386/get_syscall_args.c b/linux/i386/get_syscall_args.c
new file mode 100644
index 0000000..30cce6a
--- /dev/null
+++ b/linux/i386/get_syscall_args.c
@@ -0,0 +1,6 @@
+tcp->u_arg[0] = i386_regs.ebx;
+tcp->u_arg[1] = i386_regs.ecx;
+tcp->u_arg[2] = i386_regs.edx;
+tcp->u_arg[3] = i386_regs.esi;
+tcp->u_arg[4] = i386_regs.edi;
+tcp->u_arg[5] = i386_regs.ebp;
diff --git a/linux/i386/print_pc.c b/linux/i386/print_pc.c
new file mode 100644
index 0000000..0d5c957
--- /dev/null
+++ b/linux/i386/print_pc.c
@@ -0,0 +1 @@
+tprintf(fmt, i386_regs.eip);
diff --git a/linux/ia64/arch_getrval2.c b/linux/ia64/arch_getrval2.c
new file mode 100644
index 0000000..7a6875f
--- /dev/null
+++ b/linux/ia64/arch_getrval2.c
@@ -0,0 +1,5 @@
+long
+getrval2(struct tcb *tcp)
+{
+	return ia64_regs.gr[9];
+}
diff --git a/linux/ia64/arch_regs.c b/linux/ia64/arch_regs.c
new file mode 100644
index 0000000..d7de201
--- /dev/null
+++ b/linux/ia64/arch_regs.c
@@ -0,0 +1,7 @@
+static struct pt_all_user_regs ia64_regs;
+unsigned long *const ia64_frame_ptr = &ia64_regs.gr[12];
+
+#define IA64_PSR_IS	((long)1 << 34)
+#define ia64_ia32mode	(ia64_regs.cr_ipsr & IA64_PSR_IS)
+
+#define ARCH_REGS_FOR_GETREGS ia64_regs
diff --git a/linux/ia64/arch_sigreturn.c b/linux/ia64/arch_sigreturn.c
new file mode 100644
index 0000000..94e89cf
--- /dev/null
+++ b/linux/ia64/arch_sigreturn.c
@@ -0,0 +1,8 @@
+/* offsetof(struct sigframe, sc) */
+#define OFFSETOF_STRUCT_SIGFRAME_SC	0xA0
+const long addr = *ia64_frame_ptr + 16 +
+		  OFFSETOF_STRUCT_SIGFRAME_SC +
+		  offsetof(struct sigcontext, sc_mask);
+tprints("{mask=");
+print_sigset_addr_len(tcp, addr, NSIG / 8);
+tprints("}");
diff --git a/linux/ia64/get_error.c b/linux/ia64/get_error.c
new file mode 100644
index 0000000..fb6b9f4
--- /dev/null
+++ b/linux/ia64/get_error.c
@@ -0,0 +1,16 @@
+if (ia64_ia32mode) {
+	int err = ia64_regs.gr[8];
+	if (check_errno && is_negated_errno(err)) {
+		tcp->u_rval = -1;
+		tcp->u_error = -err;
+	} else {
+		tcp->u_rval = err;
+	}
+} else {
+	if (check_errno && ia64_regs.gr[10]) {
+		tcp->u_rval = -1;
+		tcp->u_error = ia64_regs.gr[8];
+	} else {
+		tcp->u_rval = ia64_regs.gr[8];
+	}
+}
diff --git a/linux/ia64/get_scno.c b/linux/ia64/get_scno.c
new file mode 100644
index 0000000..86333fd
--- /dev/null
+++ b/linux/ia64/get_scno.c
@@ -0,0 +1,5 @@
+if (ia64_ia32mode) {
+	scno = ia64_regs.gr[0];
+} else {
+	scno = ia64_regs.gr[15];
+}
diff --git a/linux/ia64/get_syscall_args.c b/linux/ia64/get_syscall_args.c
new file mode 100644
index 0000000..9527396
--- /dev/null
+++ b/linux/ia64/get_syscall_args.c
@@ -0,0 +1,22 @@
+if (!ia64_ia32mode) {
+	unsigned long *rbs_end =
+		(unsigned long *) ia64_regs.ar[PT_AUR_BSP];
+	unsigned long sof = (ia64_regs.cfm >> 0) & 0x7f;
+	unsigned long sol = (ia64_regs.cfm >> 7) & 0x7f;
+	unsigned long *out0 = ia64_rse_skip_regs(rbs_end, -sof + sol);
+	unsigned int i;
+
+	for (i = 0; i < tcp->s_ent->nargs; ++i) {
+		if (umoven(tcp, (unsigned long) ia64_rse_skip_regs(out0, i),
+			   sizeof(long), &tcp->u_arg[i]) < 0)
+			return -1;
+	}
+} else {
+	/* truncate away IVE sign-extension */
+	tcp->u_arg[0] = 0xffffffff & ia64_regs.gr[11]; /* EBX */
+	tcp->u_arg[1] = 0xffffffff & ia64_regs.gr[ 9]; /* ECX */
+	tcp->u_arg[2] = 0xffffffff & ia64_regs.gr[10]; /* EDX */
+	tcp->u_arg[3] = 0xffffffff & ia64_regs.gr[14]; /* ESI */
+	tcp->u_arg[4] = 0xffffffff & ia64_regs.gr[15]; /* EDI */
+	tcp->u_arg[5] = 0xffffffff & ia64_regs.gr[13]; /* EBP */
+}
diff --git a/linux/ia64/print_pc.c b/linux/ia64/print_pc.c
new file mode 100644
index 0000000..fe96780
--- /dev/null
+++ b/linux/ia64/print_pc.c
@@ -0,0 +1 @@
+tprintf(fmt, ia64_regs.br[0]);
diff --git a/linux/m68k/arch_regs.c b/linux/m68k/arch_regs.c
new file mode 100644
index 0000000..5d41825
--- /dev/null
+++ b/linux/m68k/arch_regs.c
@@ -0,0 +1 @@
+static long m68k_d0;
diff --git a/linux/m68k/arch_sigreturn.c b/linux/m68k/arch_sigreturn.c
new file mode 100644
index 0000000..c3d3ea1
--- /dev/null
+++ b/linux/m68k/arch_sigreturn.c
@@ -0,0 +1,20 @@
+long addr;
+
+if (upeek(tcp->pid, 4*PT_USP, &addr) < 0)
+	return 0;
+/* Fetch pointer to struct sigcontext.  */
+if (umove(tcp, addr + 2 * sizeof(int), &addr) < 0)
+	return 0;
+
+unsigned long mask[NSIG / 8 / sizeof(long)];
+/* Fetch first word of signal mask.  */
+if (umove(tcp, addr, &mask[0]) < 0)
+	return 0;
+
+/* Fetch remaining words of signal mask, located immediately before.  */
+addr -= sizeof(mask) - sizeof(long);
+if (umoven(tcp, addr, sizeof(mask) - sizeof(long), &mask[1]) < 0)
+	return 0;
+
+tprintsigmask_addr("{mask=", mask);
+tprints("}");
diff --git a/linux/m68k/get_error.c b/linux/m68k/get_error.c
new file mode 100644
index 0000000..8bf5359
--- /dev/null
+++ b/linux/m68k/get_error.c
@@ -0,0 +1,6 @@
+if (check_errno && is_negated_errno(m68k_d0)) {
+	tcp->u_rval = -1;
+	tcp->u_error = -m68k_d0;
+} else {
+	tcp->u_rval = m68k_d0;
+}
diff --git a/linux/m68k/get_scno.c b/linux/m68k/get_scno.c
new file mode 100644
index 0000000..1a6d28e
--- /dev/null
+++ b/linux/m68k/get_scno.c
@@ -0,0 +1,2 @@
+if (upeek(tcp->pid, 4*PT_ORIG_D0, &scno) < 0)
+	return -1;
diff --git a/linux/m68k/get_syscall_args.c b/linux/m68k/get_syscall_args.c
new file mode 100644
index 0000000..bdffcb1
--- /dev/null
+++ b/linux/m68k/get_syscall_args.c
@@ -0,0 +1,5 @@
+unsigned int i;
+
+for (i = 0; i < tcp->s_ent->nargs; ++i)
+	if (upeek(tcp->pid, (i < 5 ? i : i + 2)*4, &tcp->u_arg[i]) < 0)
+		return -1;
diff --git a/linux/m68k/get_syscall_result.c b/linux/m68k/get_syscall_result.c
new file mode 100644
index 0000000..fc452b4
--- /dev/null
+++ b/linux/m68k/get_syscall_result.c
@@ -0,0 +1,2 @@
+if (upeek(tcp->pid, 4*PT_D0, &m68k_d0) < 0)
+	return -1;
diff --git a/linux/m68k/print_pc.c b/linux/m68k/print_pc.c
new file mode 100644
index 0000000..aa4497d
--- /dev/null
+++ b/linux/m68k/print_pc.c
@@ -0,0 +1,6 @@
+long pc;
+if (upeek(tcp->pid, 4*PT_PC, &pc) < 0) {
+	PRINTBADPC;
+	return;
+}
+tprintf(fmt, pc);
diff --git a/linux/metag/arch_regs.c b/linux/metag/arch_regs.c
new file mode 100644
index 0000000..b7923ba
--- /dev/null
+++ b/linux/metag/arch_regs.c
@@ -0,0 +1,2 @@
+static struct user_gp_regs metag_regs;
+#define ARCH_REGS_FOR_GETREGSET metag_regs
diff --git a/linux/metag/get_error.c b/linux/metag/get_error.c
new file mode 100644
index 0000000..809eec5
--- /dev/null
+++ b/linux/metag/get_error.c
@@ -0,0 +1,7 @@
+/* result pointer in D0Re0 (D0.0) */
+if (check_errno && is_negated_errno(metag_regs.dx[0][0])) {
+	tcp->u_rval = -1;
+	tcp->u_error = -metag_regs.dx[0][0];
+} else {
+	tcp->u_rval = metag_regs.dx[0][0];
+}
diff --git a/linux/metag/get_scno.c b/linux/metag/get_scno.c
new file mode 100644
index 0000000..45cfa48
--- /dev/null
+++ b/linux/metag/get_scno.c
@@ -0,0 +1 @@
+scno = metag_regs.dx[0][1];	/* syscall number in D1Re0 (D1.0) */
diff --git a/linux/metag/get_syscall_args.c b/linux/metag/get_syscall_args.c
new file mode 100644
index 0000000..269f4eb
--- /dev/null
+++ b/linux/metag/get_syscall_args.c
@@ -0,0 +1,5 @@
+unsigned int i;
+
+for (i = 0; i < MAX_ARGS; i++)
+	/* arguments go backwards from D1Ar1 (D1.3) */
+	tcp->u_arg[i] = ((unsigned long *)&metag_regs.dx[3][1])[-i];
diff --git a/linux/metag/print_pc.c b/linux/metag/print_pc.c
new file mode 100644
index 0000000..4415f67
--- /dev/null
+++ b/linux/metag/print_pc.c
@@ -0,0 +1 @@
+tprintf(fmt, metag_regs.pc);
diff --git a/linux/microblaze/arch_regs.c b/linux/microblaze/arch_regs.c
new file mode 100644
index 0000000..9c26aad
--- /dev/null
+++ b/linux/microblaze/arch_regs.c
@@ -0,0 +1 @@
+static long microblaze_r3;
diff --git a/linux/microblaze/arch_sigreturn.c b/linux/microblaze/arch_sigreturn.c
new file mode 100644
index 0000000..8e2e7b8
--- /dev/null
+++ b/linux/microblaze/arch_sigreturn.c
@@ -0,0 +1,12 @@
+/* TODO: Verify that this is correct...  */
+
+long addr;
+
+/* Read r1, the stack pointer.  */
+if (upeek(tcp->pid, 1 * 4, &addr) < 0)
+	return 0;
+addr += offsetof(struct sigcontext, oldmask);
+
+tprints("{mask=");
+print_sigset_addr_len(tcp, addr, NSIG / 8);
+tprints("}");
diff --git a/linux/microblaze/get_error.c b/linux/microblaze/get_error.c
new file mode 100644
index 0000000..d36e281
--- /dev/null
+++ b/linux/microblaze/get_error.c
@@ -0,0 +1,6 @@
+if (check_errno && is_negated_errno(microblaze_r3)) {
+	tcp->u_rval = -1;
+	tcp->u_error = -microblaze_r3;
+} else {
+	tcp->u_rval = microblaze_r3;
+}
diff --git a/linux/microblaze/get_scno.c b/linux/microblaze/get_scno.c
new file mode 100644
index 0000000..cf1d919
--- /dev/null
+++ b/linux/microblaze/get_scno.c
@@ -0,0 +1,2 @@
+if (upeek(tcp->pid, 0, &scno) < 0)
+	return -1;
diff --git a/linux/microblaze/get_syscall_args.c b/linux/microblaze/get_syscall_args.c
new file mode 100644
index 0000000..373911c
--- /dev/null
+++ b/linux/microblaze/get_syscall_args.c
@@ -0,0 +1,5 @@
+unsigned int i;
+
+for (i = 0; i < tcp->s_ent->nargs; ++i)
+	if (upeek(tcp->pid, (5 + i) * 4, &tcp->u_arg[i]) < 0)
+		return -1;
diff --git a/linux/microblaze/get_syscall_result.c b/linux/microblaze/get_syscall_result.c
new file mode 100644
index 0000000..b7ec27f
--- /dev/null
+++ b/linux/microblaze/get_syscall_result.c
@@ -0,0 +1,2 @@
+if (upeek(tcp->pid, 3 * 4, &microblaze_r3) < 0)
+	return -1;
diff --git a/linux/microblaze/print_pc.c b/linux/microblaze/print_pc.c
new file mode 100644
index 0000000..b1eef14
--- /dev/null
+++ b/linux/microblaze/print_pc.c
@@ -0,0 +1,6 @@
+long pc;
+if (upeek(tcp->pid, PT_PC, &pc) < 0) {
+	PRINTBADPC;
+	return;
+}
+tprintf(fmt, pc);
diff --git a/linux/mips/arch_getrval2.c b/linux/mips/arch_getrval2.c
new file mode 100644
index 0000000..332f270
--- /dev/null
+++ b/linux/mips/arch_getrval2.c
@@ -0,0 +1,5 @@
+long
+getrval2(struct tcb *tcp)
+{
+	return mips_regs.uregs[3];
+}
diff --git a/linux/mips/arch_regs.c b/linux/mips/arch_regs.c
new file mode 100644
index 0000000..c46e6eb
--- /dev/null
+++ b/linux/mips/arch_regs.c
@@ -0,0 +1,3 @@
+struct mips_regs mips_regs; /* not static */
+/* PTRACE_GETREGS on MIPS is available since linux v2.6.15. */
+#define ARCH_REGS_FOR_GETREGS mips_regs
diff --git a/linux/mips/arch_sigreturn.c b/linux/mips/arch_sigreturn.c
new file mode 100644
index 0000000..687f871
--- /dev/null
+++ b/linux/mips/arch_sigreturn.c
@@ -0,0 +1,22 @@
+#if defined LINUX_MIPSO32
+/*
+ * offsetof(struct sigframe, sf_mask) ==
+ * sizeof(sf_ass) + sizeof(sf_pad) + sizeof(struct sigcontext)
+ */
+const long addr = mips_REG_SP + 6 * 4 +
+		  sizeof(struct sigcontext);
+#else
+/*
+ * This decodes rt_sigreturn.
+ * The 64-bit ABIs do not have sigreturn.
+ *
+ * offsetof(struct rt_sigframe, rs_uc) ==
+ * sizeof(sf_ass) + sizeof(sf_pad) + sizeof(struct siginfo)
+ */
+const long addr = mips_REG_SP + 6 * 4 + 128 +
+		  offsetof(struct ucontext, uc_sigmask);
+#endif
+
+tprints("{mask=");
+print_sigset_addr_len(tcp, addr, NSIG / 8);
+tprints("}");
diff --git a/linux/mips/get_error.c b/linux/mips/get_error.c
new file mode 100644
index 0000000..e934af0
--- /dev/null
+++ b/linux/mips/get_error.c
@@ -0,0 +1,9 @@
+if (check_errno && mips_REG_A3) {
+	tcp->u_rval = -1;
+	tcp->u_error = mips_REG_V0;
+} else {
+# if defined LINUX_MIPSN32
+	tcp->u_lrval = mips_REG_V0;
+# endif
+	tcp->u_rval = mips_REG_V0;
+}
diff --git a/linux/mips/get_scno.c b/linux/mips/get_scno.c
new file mode 100644
index 0000000..967235d
--- /dev/null
+++ b/linux/mips/get_scno.c
@@ -0,0 +1,9 @@
+scno = mips_REG_V0;
+
+if (!SCNO_IN_RANGE(scno)) {
+	if (mips_REG_A3 == 0 || mips_REG_A3 == (uint64_t) -1) {
+		if (debug_flag)
+			fprintf(stderr, "stray syscall exit: v0 = %ld\n", scno);
+		return 0;
+	}
+}
diff --git a/linux/mips/get_syscall_args.c b/linux/mips/get_syscall_args.c
new file mode 100644
index 0000000..4e4a22b
--- /dev/null
+++ b/linux/mips/get_syscall_args.c
@@ -0,0 +1,27 @@
+#if defined LINUX_MIPSN64
+	tcp->u_arg[0] = mips_REG_A0;
+	tcp->u_arg[1] = mips_REG_A1;
+	tcp->u_arg[2] = mips_REG_A2;
+	tcp->u_arg[3] = mips_REG_A3;
+	tcp->u_arg[4] = mips_REG_A4;
+	tcp->u_arg[5] = mips_REG_A5;
+#elif defined LINUX_MIPSN32
+	tcp->u_arg[0] = tcp->ext_arg[0] = mips_REG_A0;
+	tcp->u_arg[1] = tcp->ext_arg[1] = mips_REG_A1;
+	tcp->u_arg[2] = tcp->ext_arg[2] = mips_REG_A2;
+	tcp->u_arg[3] = tcp->ext_arg[3] = mips_REG_A3;
+	tcp->u_arg[4] = tcp->ext_arg[4] = mips_REG_A4;
+	tcp->u_arg[5] = tcp->ext_arg[5] = mips_REG_A5;
+#elif defined LINUX_MIPSO32
+	tcp->u_arg[0] = mips_REG_A0;
+	tcp->u_arg[1] = mips_REG_A1;
+	tcp->u_arg[2] = mips_REG_A2;
+	tcp->u_arg[3] = mips_REG_A3;
+	if (tcp->s_ent->nargs > 4) {
+		umoven(tcp, mips_REG_SP + 4 * 4,
+		       (tcp->s_ent->nargs - 4) * sizeof(tcp->u_arg[0]),
+		       &tcp->u_arg[4]);
+	}
+#else
+# error unsupported mips abi
+#endif
diff --git a/linux/mips/print_pc.c b/linux/mips/print_pc.c
new file mode 100644
index 0000000..569b0b6
--- /dev/null
+++ b/linux/mips/print_pc.c
@@ -0,0 +1 @@
+tprintf(fmt, (unsigned long) mips_REG_EPC);
diff --git a/linux/or1k/arch_regs.c b/linux/or1k/arch_regs.c
new file mode 100644
index 0000000..7415e08
--- /dev/null
+++ b/linux/or1k/arch_regs.c
@@ -0,0 +1,2 @@
+static struct user_regs_struct or1k_regs;
+#define ARCH_REGS_FOR_GETREGSET or1k_regs
diff --git a/linux/or1k/get_error.c b/linux/or1k/get_error.c
new file mode 100644
index 0000000..cbf9a6e
--- /dev/null
+++ b/linux/or1k/get_error.c
@@ -0,0 +1,6 @@
+if (check_errno && is_negated_errno(or1k_regs.gpr[11])) {
+	tcp->u_rval = -1;
+	tcp->u_error = -or1k_regs.gpr[11];
+} else {
+	tcp->u_rval = or1k_regs.gpr[11];
+}
diff --git a/linux/or1k/get_scno.c b/linux/or1k/get_scno.c
new file mode 100644
index 0000000..99fada2
--- /dev/null
+++ b/linux/or1k/get_scno.c
@@ -0,0 +1 @@
+scno = or1k_regs.gpr[11];
diff --git a/linux/or1k/get_syscall_args.c b/linux/or1k/get_syscall_args.c
new file mode 100644
index 0000000..751cba0
--- /dev/null
+++ b/linux/or1k/get_syscall_args.c
@@ -0,0 +1,6 @@
+tcp->u_arg[0] = or1k_regs.gpr[3 + 0];
+tcp->u_arg[1] = or1k_regs.gpr[3 + 1];
+tcp->u_arg[2] = or1k_regs.gpr[3 + 2];
+tcp->u_arg[3] = or1k_regs.gpr[3 + 3];
+tcp->u_arg[4] = or1k_regs.gpr[3 + 4];
+tcp->u_arg[5] = or1k_regs.gpr[3 + 5];
diff --git a/linux/or1k/print_pc.c b/linux/or1k/print_pc.c
new file mode 100644
index 0000000..3fe4a1a
--- /dev/null
+++ b/linux/or1k/print_pc.c
@@ -0,0 +1 @@
+tprintf(fmt, or1k_regs.pc);
diff --git a/linux/powerpc/arch_regs.c b/linux/powerpc/arch_regs.c
new file mode 100644
index 0000000..cd92d21
--- /dev/null
+++ b/linux/powerpc/arch_regs.c
@@ -0,0 +1,3 @@
+struct pt_regs ppc_regs; /* not static */
+
+#define ARCH_REGS_FOR_GETREGS ppc_regs
diff --git a/linux/powerpc/arch_sigreturn.c b/linux/powerpc/arch_sigreturn.c
new file mode 100644
index 0000000..bc4802a
--- /dev/null
+++ b/linux/powerpc/arch_sigreturn.c
@@ -0,0 +1,24 @@
+long esp = ppc_regs.gpr[1];
+struct sigcontext sc;
+
+/* Skip dummy stack frame. */
+#ifdef POWERPC64
+if (current_personality == 0)
+	esp += 128;
+else
+#endif
+	esp += 64;
+
+if (umove(tcp, esp, &sc) < 0) {
+	tprintf("{mask=%#lx}", esp);
+} else {
+	unsigned long mask[NSIG / 8 / sizeof(long)];
+#ifdef POWERPC64
+	mask[0] = sc.oldmask | (sc._unused[3] << 32);
+#else
+	mask[0] = sc.oldmask;
+	mask[1] = sc._unused[3];
+#endif
+	tprintsigmask_addr("{mask=", mask);
+	tprints("}");
+}
diff --git a/linux/powerpc/get_error.c b/linux/powerpc/get_error.c
new file mode 100644
index 0000000..f0f0a4e
--- /dev/null
+++ b/linux/powerpc/get_error.c
@@ -0,0 +1,6 @@
+if (check_errno && (ppc_regs.ccr & 0x10000000)) {
+	tcp->u_rval = -1;
+	tcp->u_error = ppc_regs.gpr[3];
+} else {
+	tcp->u_rval = ppc_regs.gpr[3];
+}
diff --git a/linux/powerpc/get_scno.c b/linux/powerpc/get_scno.c
new file mode 100644
index 0000000..a311734
--- /dev/null
+++ b/linux/powerpc/get_scno.c
@@ -0,0 +1 @@
+scno = ppc_regs.gpr[0];
diff --git a/linux/powerpc/get_syscall_args.c b/linux/powerpc/get_syscall_args.c
new file mode 100644
index 0000000..237cf77
--- /dev/null
+++ b/linux/powerpc/get_syscall_args.c
@@ -0,0 +1,6 @@
+tcp->u_arg[0] = ppc_regs.orig_gpr3;
+tcp->u_arg[1] = ppc_regs.gpr[4];
+tcp->u_arg[2] = ppc_regs.gpr[5];
+tcp->u_arg[3] = ppc_regs.gpr[6];
+tcp->u_arg[4] = ppc_regs.gpr[7];
+tcp->u_arg[5] = ppc_regs.gpr[8];
diff --git a/linux/powerpc/getregs_old.c b/linux/powerpc/getregs_old.c
new file mode 100644
index 0000000..22167cb
--- /dev/null
+++ b/linux/powerpc/getregs_old.c
@@ -0,0 +1,35 @@
+/*
+ * PTRACE_GETREGS was added to the PowerPC kernel in v2.6.23,
+ * we provide a slow fallback for old kernels.
+ */
+static int
+getregs_old(pid_t pid)
+{
+	int i;
+	long r;
+
+	if (iflag) {
+		r = upeek(pid, sizeof(long) * PT_NIP, (long *)&ppc_regs.nip);
+		if (r)
+			goto out;
+	}
+#ifdef POWERPC64 /* else we never use it */
+	r = upeek(pid, sizeof(long) * PT_MSR, (long *)&ppc_regs.msr);
+	if (r)
+		goto out;
+#endif
+	r = upeek(pid, sizeof(long) * PT_CCR, (long *)&ppc_regs.ccr);
+	if (r)
+		goto out;
+	r = upeek(pid, sizeof(long) * PT_ORIG_R3, (long *)&ppc_regs.orig_gpr3);
+	if (r)
+		goto out;
+	for (i = 0; i <= 8; i++) {
+		r = upeek(pid, sizeof(long) * (PT_R0 + i),
+			  (long *)&ppc_regs.gpr[i]);
+		if (r)
+			goto out;
+	}
+ out:
+	return r;
+}
diff --git a/linux/powerpc/print_pc.c b/linux/powerpc/print_pc.c
new file mode 100644
index 0000000..34112fb
--- /dev/null
+++ b/linux/powerpc/print_pc.c
@@ -0,0 +1 @@
+tprintf(fmt, ppc_regs.nip);
diff --git a/linux/powerpc64/arch_regs.c b/linux/powerpc64/arch_regs.c
new file mode 100644
index 0000000..b5c572d
--- /dev/null
+++ b/linux/powerpc64/arch_regs.c
@@ -0,0 +1 @@
+#include "powerpc/arch_regs.c"
diff --git a/linux/powerpc64/arch_sigreturn.c b/linux/powerpc64/arch_sigreturn.c
new file mode 100644
index 0000000..316022f
--- /dev/null
+++ b/linux/powerpc64/arch_sigreturn.c
@@ -0,0 +1 @@
+#include "powerpc/arch_sigreturn.c"
diff --git a/linux/powerpc64/get_error.c b/linux/powerpc64/get_error.c
new file mode 100644
index 0000000..209bfd8
--- /dev/null
+++ b/linux/powerpc64/get_error.c
@@ -0,0 +1 @@
+#include "powerpc/get_error.c"
diff --git a/linux/powerpc64/get_scno.c b/linux/powerpc64/get_scno.c
new file mode 100644
index 0000000..1e67010
--- /dev/null
+++ b/linux/powerpc64/get_scno.c
@@ -0,0 +1,11 @@
+scno = ppc_regs.gpr[0];
+unsigned int currpers;
+
+/*
+ * Check for 64/32 bit mode.
+ * Embedded implementations covered by Book E extension of PPC use
+ * bit 0 (CM) of 32-bit Machine state register (MSR).
+ * Other implementations use bit 0 (SF) of 64-bit MSR.
+ */
+currpers = (ppc_regs.msr & 0x8000000080000000) ? 0 : 1;
+update_personality(tcp, currpers);
diff --git a/linux/powerpc64/get_syscall_args.c b/linux/powerpc64/get_syscall_args.c
new file mode 100644
index 0000000..5561a55
--- /dev/null
+++ b/linux/powerpc64/get_syscall_args.c
@@ -0,0 +1 @@
+#include "powerpc/get_syscall_args.c"
diff --git a/linux/powerpc64/getregs_old.c b/linux/powerpc64/getregs_old.c
new file mode 100644
index 0000000..177ff74
--- /dev/null
+++ b/linux/powerpc64/getregs_old.c
@@ -0,0 +1 @@
+#include "powerpc/getregs_old.c"
diff --git a/linux/powerpc64/print_pc.c b/linux/powerpc64/print_pc.c
new file mode 100644
index 0000000..ddaf880
--- /dev/null
+++ b/linux/powerpc64/print_pc.c
@@ -0,0 +1 @@
+#include "powerpc/print_pc.c"
diff --git a/linux/s390/arch_regs.c b/linux/s390/arch_regs.c
new file mode 100644
index 0000000..32c50a1
--- /dev/null
+++ b/linux/s390/arch_regs.c
@@ -0,0 +1,4 @@
+/* PTRACE_GETREGSET on S390 is available since linux v2.6.27. */
+static struct user_regs_struct s390_regset;
+unsigned long *const s390_frame_ptr = &s390_regset.gprs[15];
+#define ARCH_REGS_FOR_GETREGSET s390_regset
diff --git a/linux/s390/arch_sigreturn.c b/linux/s390/arch_sigreturn.c
new file mode 100644
index 0000000..43afd95
--- /dev/null
+++ b/linux/s390/arch_sigreturn.c
@@ -0,0 +1,14 @@
+long mask[NSIG / 8 / sizeof(long)];
+const long addr = *s390_frame_ptr + __SIGNAL_FRAMESIZE;
+
+if (umove(tcp, addr, &mask) < 0) {
+	tprintf("{mask=%#lx}", addr);
+} else {
+#ifdef S390
+	long v = mask[0];
+	mask[0] = mask[1];
+	mask[1] = v;
+#endif
+	tprintsigmask_addr("{mask=", mask);
+	tprints("}");
+}
diff --git a/linux/s390/get_error.c b/linux/s390/get_error.c
new file mode 100644
index 0000000..29fffbd
--- /dev/null
+++ b/linux/s390/get_error.c
@@ -0,0 +1,6 @@
+if (check_errno && is_negated_errno(s390_regset.gprs[2])) {
+	tcp->u_rval = -1;
+	tcp->u_error = -s390_regset.gprs[2];
+} else {
+	tcp->u_rval = s390_regset.gprs[2];
+}
diff --git a/linux/s390/get_scno.c b/linux/s390/get_scno.c
new file mode 100644
index 0000000..b9e1c19
--- /dev/null
+++ b/linux/s390/get_scno.c
@@ -0,0 +1 @@
+scno = s390_regset.gprs[2];
diff --git a/linux/s390/get_syscall_args.c b/linux/s390/get_syscall_args.c
new file mode 100644
index 0000000..85f2585
--- /dev/null
+++ b/linux/s390/get_syscall_args.c
@@ -0,0 +1,6 @@
+tcp->u_arg[0] = s390_regset.orig_gpr2;
+tcp->u_arg[1] = s390_regset.gprs[3];
+tcp->u_arg[2] = s390_regset.gprs[4];
+tcp->u_arg[3] = s390_regset.gprs[5];
+tcp->u_arg[4] = s390_regset.gprs[6];
+tcp->u_arg[5] = s390_regset.gprs[7];
diff --git a/linux/s390/print_pc.c b/linux/s390/print_pc.c
new file mode 100644
index 0000000..f92ccd4
--- /dev/null
+++ b/linux/s390/print_pc.c
@@ -0,0 +1 @@
+tprintf(fmt, s390_regset.psw.addr);
diff --git a/linux/s390x/arch_regs.c b/linux/s390x/arch_regs.c
new file mode 100644
index 0000000..62aece7
--- /dev/null
+++ b/linux/s390x/arch_regs.c
@@ -0,0 +1 @@
+#include "s390/arch_regs.c"
diff --git a/linux/s390x/arch_sigreturn.c b/linux/s390x/arch_sigreturn.c
new file mode 100644
index 0000000..679a395
--- /dev/null
+++ b/linux/s390x/arch_sigreturn.c
@@ -0,0 +1 @@
+#include "s390/arch_sigreturn.c"
diff --git a/linux/s390x/get_error.c b/linux/s390x/get_error.c
new file mode 100644
index 0000000..8e3944c
--- /dev/null
+++ b/linux/s390x/get_error.c
@@ -0,0 +1 @@
+#include "s390/get_error.c"
diff --git a/linux/s390x/get_scno.c b/linux/s390x/get_scno.c
new file mode 100644
index 0000000..71816fb
--- /dev/null
+++ b/linux/s390x/get_scno.c
@@ -0,0 +1 @@
+#include "s390/get_scno.c"
diff --git a/linux/s390x/get_syscall_args.c b/linux/s390x/get_syscall_args.c
new file mode 100644
index 0000000..4ded41d
--- /dev/null
+++ b/linux/s390x/get_syscall_args.c
@@ -0,0 +1 @@
+#include "s390/get_syscall_args.c"
diff --git a/linux/s390x/print_pc.c b/linux/s390x/print_pc.c
new file mode 100644
index 0000000..9a445f7
--- /dev/null
+++ b/linux/s390x/print_pc.c
@@ -0,0 +1 @@
+#include "s390/print_pc.c"
diff --git a/linux/sh/arch_getrval2.c b/linux/sh/arch_getrval2.c
new file mode 100644
index 0000000..8f60de7
--- /dev/null
+++ b/linux/sh/arch_getrval2.c
@@ -0,0 +1,8 @@
+long
+getrval2(struct tcb *tcp)
+{
+	long val;
+	if (upeek(tcp->pid, 4*(REG_REG0+1), &val) < 0)
+		return -1;
+	return val;
+}
diff --git a/linux/sh/arch_regs.c b/linux/sh/arch_regs.c
new file mode 100644
index 0000000..9d24ee7
--- /dev/null
+++ b/linux/sh/arch_regs.c
@@ -0,0 +1 @@
+static long sh_r0;
diff --git a/linux/sh/get_error.c b/linux/sh/get_error.c
new file mode 100644
index 0000000..2375e3c
--- /dev/null
+++ b/linux/sh/get_error.c
@@ -0,0 +1,6 @@
+if (check_errno && is_negated_errno(sh_r0)) {
+	tcp->u_rval = -1;
+	tcp->u_error = -sh_r0;
+} else {
+	tcp->u_rval = sh_r0;
+}
diff --git a/linux/sh/get_scno.c b/linux/sh/get_scno.c
new file mode 100644
index 0000000..90dbf0f
--- /dev/null
+++ b/linux/sh/get_scno.c
@@ -0,0 +1,19 @@
+/*
+ * In the new syscall ABI, the system call number is in R3.
+ */
+if (upeek(tcp->pid, 4*(REG_REG0+3), &scno) < 0)
+	return -1;
+
+if (scno < 0) {
+	/* Odd as it may seem, a glibc bug has been known to cause
+	   glibc to issue bogus negative syscall numbers.  So for
+	   our purposes, make strace print what it *should* have been */
+	long correct_scno = (scno & 0xff);
+	if (debug_flag)
+		fprintf(stderr,
+			"Detected glibc bug: bogus system call"
+			" number = %ld, correcting to %ld\n",
+			scno,
+			correct_scno);
+	scno = correct_scno;
+}
diff --git a/linux/sh/get_syscall_args.c b/linux/sh/get_syscall_args.c
new file mode 100644
index 0000000..7c94f48
--- /dev/null
+++ b/linux/sh/get_syscall_args.c
@@ -0,0 +1,10 @@
+static const int syscall_regs[MAX_ARGS] = {
+	4 * (REG_REG0+4), 4 * (REG_REG0+5), 4 * (REG_REG0+6),
+	4 * (REG_REG0+7), 4 * (REG_REG0  ), 4 * (REG_REG0+1)
+};
+
+unsigned int i;
+
+for (i = 0; i < tcp->s_ent->nargs; ++i)
+	if (upeek(tcp->pid, syscall_regs[i], &tcp->u_arg[i]) < 0)
+		return -1;
diff --git a/linux/sh/get_syscall_result.c b/linux/sh/get_syscall_result.c
new file mode 100644
index 0000000..3ee0546
--- /dev/null
+++ b/linux/sh/get_syscall_result.c
@@ -0,0 +1,3 @@
+/* new syscall ABI returns result in R0 */
+if (upeek(tcp->pid, 4*REG_REG0, (long *)&sh_r0) < 0)
+	return -1;
diff --git a/linux/sh/print_pc.c b/linux/sh/print_pc.c
new file mode 100644
index 0000000..2f43eff
--- /dev/null
+++ b/linux/sh/print_pc.c
@@ -0,0 +1,6 @@
+long pc;
+if (upeek(tcp->pid, 4*REG_PC, &pc) < 0) {
+	PRINTBADPC;
+	return;
+}
+tprintf(fmt, pc);
diff --git a/linux/sh64/arch_regs.c b/linux/sh64/arch_regs.c
new file mode 100644
index 0000000..e09cac5
--- /dev/null
+++ b/linux/sh64/arch_regs.c
@@ -0,0 +1 @@
+static long sh64_r9;
diff --git a/linux/sh64/get_error.c b/linux/sh64/get_error.c
new file mode 100644
index 0000000..9e8aeaf
--- /dev/null
+++ b/linux/sh64/get_error.c
@@ -0,0 +1,6 @@
+if (check_errno && is_negated_errno(sh64_r9)) {
+	tcp->u_rval = -1;
+	tcp->u_error = -sh64_r9;
+} else {
+	tcp->u_rval = sh64_r9;
+}
diff --git a/linux/sh64/get_scno.c b/linux/sh64/get_scno.c
new file mode 100644
index 0000000..9e7ecd4
--- /dev/null
+++ b/linux/sh64/get_scno.c
@@ -0,0 +1,3 @@
+if (upeek(tcp->pid, REG_SYSCALL, &scno) < 0)
+	return -1;
+scno &= 0xFFFF;
diff --git a/linux/sh64/get_syscall_args.c b/linux/sh64/get_syscall_args.c
new file mode 100644
index 0000000..dcc8967
--- /dev/null
+++ b/linux/sh64/get_syscall_args.c
@@ -0,0 +1,7 @@
+/* Registers used by SH5 Linux system calls for parameters */
+static const int syscall_regs[MAX_ARGS] = { 2, 3, 4, 5, 6, 7 };
+unsigned int i;
+
+for (i = 0; i < tcp->s_ent->nargs; ++i)
+	if (upeek(tcp->pid, REG_GENERAL(syscall_regs[i]), &tcp->u_arg[i]) < 0)
+		return -1;
diff --git a/linux/sh64/get_syscall_result.c b/linux/sh64/get_syscall_result.c
new file mode 100644
index 0000000..e53bd0f
--- /dev/null
+++ b/linux/sh64/get_syscall_result.c
@@ -0,0 +1,3 @@
+/* ABI defines result returned in r9 */
+if (upeek(tcp->pid, REG_GENERAL(9), (long *)&sh64_r9) < 0)
+	return -1;
diff --git a/linux/sh64/print_pc.c b/linux/sh64/print_pc.c
new file mode 100644
index 0000000..c0232e5
--- /dev/null
+++ b/linux/sh64/print_pc.c
@@ -0,0 +1,6 @@
+long pc;
+if (upeek(tcp->pid, REG_PC, &pc) < 0) {
+	PRINTBADPC;
+	return;
+}
+tprintf(fmt, pc);
diff --git a/linux/sparc/arch_getrval2.c b/linux/sparc/arch_getrval2.c
new file mode 100644
index 0000000..9079482
--- /dev/null
+++ b/linux/sparc/arch_getrval2.c
@@ -0,0 +1,5 @@
+long
+getrval2(struct tcb *tcp)
+{
+	return sparc_regs.u_regs[U_REG_O1];
+}
diff --git a/linux/sparc/arch_regs.c b/linux/sparc/arch_regs.c
new file mode 100644
index 0000000..ed13029
--- /dev/null
+++ b/linux/sparc/arch_regs.c
@@ -0,0 +1,2 @@
+struct pt_regs sparc_regs; /* not static */
+#define ARCH_REGS_FOR_GETREGS sparc_regs
diff --git a/linux/sparc/arch_sigreturn.c b/linux/sparc/arch_sigreturn.c
new file mode 100644
index 0000000..144b3a6
--- /dev/null
+++ b/linux/sparc/arch_sigreturn.c
@@ -0,0 +1,19 @@
+long fp = sparc_regs.u_regs[U_REG_FP] + sizeof(struct sparc_stackf);
+struct {
+	struct pt_regs si_regs;
+	int si_mask;
+	void *fpu_save;
+	long insns[2] ATTRIBUTE_ALIGNED(8);
+	unsigned int extramask[NSIG / 8 / sizeof(int) - 1];
+} frame;
+
+if (umove(tcp, fp, &frame) < 0) {
+	tprintf("{mask=%#lx}", fp);
+} else {
+	unsigned int mask[NSIG / 8 / sizeof(int)];
+
+	mask[0] = frame.si_mask;
+	memcpy(mask + 1, frame.extramask, sizeof(frame.extramask));
+	tprintsigmask_addr("{mask=", mask);
+	tprints("}");
+}
diff --git a/linux/sparc/dummy2.h b/linux/sparc/dummy2.h
deleted file mode 100644
index 783d4ee..0000000
--- a/linux/sparc/dummy2.h
+++ /dev/null
@@ -1,276 +0,0 @@
-/*
- * Copyright (c) 1993, 1994, 1995 Rick Sladkey <jrs@world.std.com>
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- * 3. The name of the author may not be used to endorse or promote products
- *    derived from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-/* still unfinished */
-
-#define solaris_sysmp printargs
-#define solaris_sginap printargs
-#define solaris_sgikopt printargs
-#define solaris_sysmips printargs
-#define solaris_sigreturn printargs
-#define solaris_recvmsg printargs
-#define solaris_sendmsg printargs
-#define solaris_nfssvc printargs
-#define solaris_getfh printargs
-#define solaris_async_daemon printargs
-#define solaris_exportfs printargs
-#define solaris_BSD_getime printargs
-#define solaris_sproc printargs
-#define solaris_procblk printargs
-#define solaris_sprocsp printargs
-#define solaris_msync printargs
-#define solaris_madvise printargs
-#define solaris_pagelock printargs
-#define solaris_quotactl printargs
-#define solaris_cacheflush printargs
-#define solaris_cachectl printargs
-#define solaris_nuname printargs
-#define solaris_sigpoll printargs
-#define solaris_swapctl printargs
-#define solaris_sigstack printargs
-#define solaris_sigsendset printargs
-#define solaris_priocntl printargs
-#define solaris_ksigqueue printargs
-#define solaris_lwp_sema_wait printargs
-#define solaris_memcntl printargs
-#define solaris_syscall printargs
-#define solaris_clocal printargs
-#define solaris_syssun printargs
-#define solaris_sysi86 printargs
-#define solaris_sysmachine printargs
-#define solaris_plock printargs
-#define solaris_pathconf printargs
-#define solaris_sigtimedwait printargs
-#define solaris_ulimit printargs
-#define solaris_ptrace printargs
-#define solaris_stty printargs
-#define solaris_lwp_info printargs
-#define solaris_priocntlsys printargs
-#define solaris_hrtsys printargs
-#define solaris_xenix printargs
-#define solaris_statfs printargs
-#define solaris_fstatfs printargs
-#define solaris_statvfs printargs
-#define solaris_fstatvfs printargs
-#define solaris_fork1 printargs
-#define solaris_sigsendsys printargs
-#define solaris_gtty printargs
-#define solaris_vtrace printargs
-#define solaris_fpathconf printargs
-#define solaris_evsys printargs
-#define solaris_acct printargs
-#define solaris_exec printargs
-#define solaris_lwp_sema_post printargs
-#define solaris_nfssys printargs
-#define solaris_sigaltstack printargs
-#define solaris_uadmin printargs
-#define solaris_umount printargs
-#define solaris_modctl printargs
-#define solaris_acancel printargs
-#define solaris_async printargs
-#define solaris_evtrapret printargs
-#define solaris_lwp_create printargs
-#define solaris_lwp_exit printargs
-#define solaris_lwp_suspend printargs
-#define solaris_lwp_continue printargs
-#define solaris_lwp_kill printargs
-#define solaris_lwp_self printargs
-#define solaris_lwp_setprivate printargs
-#define solaris_lwp_getprivate printargs
-#define solaris_lwp_wait printargs
-#define solaris_lwp_mutex_unlock printargs
-#define solaris_lwp_mutex_lock printargs
-#define solaris_lwp_cond_wait printargs
-#define solaris_lwp_cond_signal printargs
-#define solaris_lwp_cond_broadcast printargs
-#define solaris_llseek printargs
-#define solaris_inst_sync printargs
-#define solaris_auditsys printargs
-#define solaris_processor_bind printargs
-#define solaris_processor_info printargs
-#define solaris_p_online printargs
-#define solaris_sigqueue printargs
-#define solaris_clock_gettime printargs
-#define solaris_clock_settime printargs
-#define solaris_clock_getres printargs
-#define solaris_nanosleep printargs
-#define solaris_timer_create printargs
-#define solaris_timer_delete printargs
-#define solaris_timer_settime printargs
-#define solaris_timer_gettime printargs
-#define solaris_timer_getoverrun printargs
-#define solaris_signal printargs
-#define solaris_sigset printargs
-#define solaris_sighold printargs
-#define solaris_sigrelse printargs
-#define solaris_sigignore printargs
-#define solaris_sigpause printargs
-#define solaris_msgctl printargs
-#define solaris_msgget printargs
-#define solaris_msgrcv printargs
-#define solaris_msgsnd printargs
-#define solaris_shmat printargs
-#define solaris_shmctl printargs
-#define solaris_shmdt printargs
-#define solaris_shmget printargs
-#define solaris_semctl printargs
-#define solaris_semget printargs
-#define solaris_semop printargs
-#define solaris_olduname printargs
-#define solaris_ustat printargs
-#define solaris_fusers printargs
-#define solaris_sysfs1 printargs
-#define solaris_sysfs2 printargs
-#define solaris_sysfs3 printargs
-
-/* like another call */
-#define solaris_lchown solaris_chown
-#define solaris_setuid solaris_close
-#define solaris_seteuid solaris_close
-#define solaris_setgid solaris_close
-#define solaris_setegid solaris_close
-#define solaris_vhangup solaris_close
-#define solaris_fdsync solaris_close
-#define solaris_sigfillset solaris_sigpending
-#define solaris_vfork solaris_fork
-#define solaris_ksigaction solaris_sigaction
-#define solaris_BSDgetpgrp solaris_getpgrp
-#define solaris_BSDsetpgrp solaris_setpgrp
-#define solaris_waitsys solaris_waitid
-
-/* printargs does the right thing */
-#define solaris_sync printargs
-#define solaris_profil printargs
-#define solaris_yield printargs
-#define solaris_pause printargs
-#define solaris_sethostid printargs
-
-/* subfunction entry points */
-#define solaris_pgrpsys printargs
-#define solaris_sigcall printargs
-#define solaris_msgsys printargs
-#define solaris_shmsys printargs
-#define solaris_semsys printargs
-#define solaris_utssys printargs
-#define solaris_sysfs printargs
-#define solaris_spcall printargs
-#define solaris_context printargs
-
-/* same as linux */
-#define solaris_exit sys_exit
-#define solaris_fork sys_fork
-#define solaris_read sys_read
-#define solaris_write sys_write
-#define solaris_close sys_close
-#define solaris_creat sys_creat
-#define solaris_link sys_link
-#define solaris_unlink sys_unlink
-#define solaris_chdir sys_chdir
-#define solaris_time sys_time
-#define solaris_chmod sys_chmod
-#define solaris_lseek sys_lseek
-#define solaris_stime sys_stime
-#define solaris_alarm sys_alarm
-#define solaris_utime sys_utime
-#define solaris_access sys_access
-#define solaris_nice sys_nice
-#define solaris_dup sys_dup
-#define solaris_pipe sys_pipe
-#define solaris_times sys_times
-#define solaris_execve sys_execve
-#define solaris_umask sys_umask
-#define solaris_chroot sys_chroot
-#define solaris_rmdir sys_rmdir
-#define solaris_mkdir sys_mkdir
-#define solaris_getdents sys_getdents
-#define solaris_poll sys_poll
-#define solaris_symlink sys_symlink
-#define solaris_readlink sys_readlink
-#define solaris_setgroups sys_setgroups
-#define solaris_getgroups sys_getgroups
-#define solaris_fchmod sys_fchmod
-#define solaris_fchown sys_fchown
-#define solaris_mprotect sys_mprotect
-#define solaris_munmap sys_munmap
-#define solaris_readv sys_readv
-#define solaris_writev sys_writev
-#define solaris_chown sys_chown
-#define solaris_rename sys_rename
-#define solaris_gettimeofday sys_gettimeofday
-#define solaris_getitimer sys_getitimer
-#define solaris_setitimer sys_setitimer
-#define solaris_brk sys_brk
-#define solaris_mmap sys_mmap
-#define solaris_getsid sys_getsid
-#define solaris_setsid sys_setsid
-#define solaris_getpgid sys_getpgid
-#define solaris_setpgid sys_setpgid
-#define solaris_getpgrp sys_getpgrp
-
-/* These are handled according to current_personality */
-#define solaris_xstat sys_xstat
-#define solaris_fxstat sys_fxstat
-#define solaris_lxstat sys_xstat
-#define solaris_xmknod sys_xmknod
-#define solaris_stat sys_stat
-#define solaris_fstat sys_fstat
-#define solaris_lstat sys_lstat
-#define solaris_pread sys_pread
-#define solaris_pwrite sys_pwrite
-#define solaris_ioctl sys_ioctl
-#define solaris_mknod sys_mknod
-
-/* To be done */
-#define solaris_mount printargs
-#define solaris_sysinfo printargs
-#define solaris_sysconfig printargs
-#define solaris_getpmsg printargs
-#define solaris_putpmsg printargs
-#define solaris_wait printargs
-#define solaris_waitid printargs
-#define solaris_sigsuspend printargs
-#define solaris_setpgrp printargs
-#define solaris_getcontext printargs
-#define solaris_setcontext printargs
-#define solaris_getpid printargs
-#define solaris_getuid printargs
-#define solaris_kill printargs
-#define solaris_getgid printargs
-#define solaris_fcntl printargs
-#define solaris_getmsg printargs
-#define solaris_putmsg printargs
-#define solaris_sigprocmask printargs
-#define solaris_sigaction printargs
-#define solaris_sigpending printargs
-#define solaris_mincore printargs
-#define solaris_fchdir printargs
-#define solaris_setrlimit printargs
-#define solaris_getrlimit printargs
-#define solaris_uname printargs
-#define solaris_adjtime printargs
-#define solaris_fchroot printargs
-#define solaris_utimes printargs
diff --git a/linux/sparc/errnoent1.h b/linux/sparc/errnoent1.h
deleted file mode 100644
index e4311a4..0000000
--- a/linux/sparc/errnoent1.h
+++ /dev/null
@@ -1,116 +0,0 @@
-[  1] = "EPERM",
-[  2] = "ENOENT",
-[  3] = "ESRCH",
-[  4] = "EINTR",
-[  5] = "EIO",
-[  6] = "ENXIO",
-[  7] = "E2BIG",
-[  8] = "ENOEXEC",
-[  9] = "EBADF",
-[ 10] = "ECHILD",
-[ 11] = "EAGAIN",
-[ 12] = "ENOMEM",
-[ 13] = "EACCES",
-[ 14] = "EFAULT",
-[ 15] = "ENOTBLK",
-[ 16] = "EBUSY",
-[ 17] = "EEXIST",
-[ 18] = "EXDEV",
-[ 19] = "ENODEV",
-[ 20] = "ENOTDIR",
-[ 21] = "EISDIR",
-[ 22] = "EINVAL",
-[ 23] = "ENFILE",
-[ 24] = "EMFILE",
-[ 25] = "ENOTTY",
-[ 26] = "ETXTBSY",
-[ 27] = "EFBIG",
-[ 28] = "ENOSPC",
-[ 29] = "ESPIPE",
-[ 30] = "EROFS",
-[ 31] = "EMLINK",
-[ 32] = "EPIPE",
-[ 33] = "EDOM",
-[ 34] = "ERANGE",
-[ 35] = "ENOMSG",
-[ 36] = "EIDRM",
-[ 37] = "ECHRNG",
-[ 38] = "EL2NSYNC",
-[ 39] = "EL3HLT",
-[ 40] = "EL3RST",
-[ 41] = "ELNRNG",
-[ 42] = "EUNATCH",
-[ 43] = "ENOCSI",
-[ 44] = "EL2HLT",
-[ 45] = "EDEADLK",
-[ 46] = "ENOLCK",
-[ 47] = "ECANCELED",
-[ 48] = "ENOTSUP",
-[ 50] = "EBADE",
-[ 51] = "EBADR",
-[ 52] = "EXFULL",
-[ 53] = "ENOANO",
-[ 54] = "EBADRQC",
-[ 55] = "EBADSLT",
-[ 56] = "EDEADLOCK",
-[ 57] = "EBFONT",
-[ 60] = "ENOSTR",
-[ 61] = "ENODATA",
-[ 62] = "ETIME",
-[ 63] = "ENOSR",
-[ 64] = "ENONET",
-[ 65] = "ENOPKG",
-[ 66] = "EREMOTE",
-[ 67] = "ENOLINK",
-[ 68] = "EADV",
-[ 69] = "ESRMNT",
-[ 70] = "ECOMM",
-[ 71] = "EPROTO",
-[ 74] = "EMULTIHOP",
-[ 77] = "EBADMSG",
-[ 78] = "ENAMETOOLONG",
-[ 79] = "EOVERFLOW",
-[ 80] = "ENOTUNIQ",
-[ 81] = "EBADFD",
-[ 82] = "EREMCHG",
-[ 83] = "ELIBACC",
-[ 84] = "ELIBBAD",
-[ 85] = "ELIBSCN",
-[ 86] = "ELIBMAX",
-[ 87] = "ELIBEXEC",
-[ 88] = "EILSEQ",
-[ 89] = "ENOSYS",
-[ 90] = "ELOOP",
-[ 91] = "ERESTART",
-[ 92] = "ESTRPIPE",
-[ 93] = "ENOTEMPTY",
-[ 94] = "EUSERS",
-[ 95] = "ENOTSOCK",
-[ 96] = "EDESTADDRREQ",
-[ 97] = "EMSGSIZE",
-[ 98] = "EPROTOTYPE",
-[ 99] = "ENOPROTOOPT",
-[120] = "EPROTONOSUPPORT",
-[121] = "ESOCKTNOSUPPORT",
-[122] = "EOPNOTSUPP",
-[123] = "EPFNOSUPPORT",
-[124] = "EAFNOSUPPORT",
-[125] = "EADDRINUSE",
-[126] = "EADDRNOTAVAIL",
-[127] = "ENETDOWN",
-[128] = "ENETUNREACH",
-[129] = "ENETRESET",
-[130] = "ECONNABORTED",
-[131] = "ECONNRESET",
-[132] = "ENOBUFS",
-[133] = "EISCONN",
-[134] = "ENOTCONN",
-[143] = "ESHUTDOWN",
-[144] = "ETOOMANYREFS",
-[145] = "ETIMEDOUT",
-[146] = "ECONNREFUSED",
-[147] = "EHOSTDOWN",
-[148] = "EHOSTUNREACH",
-[149] = "EALREADY",
-[150] = "EINPROGRESS",
-[151] = "ESTALE",
diff --git a/linux/sparc/get_error.c b/linux/sparc/get_error.c
new file mode 100644
index 0000000..3531f01
--- /dev/null
+++ b/linux/sparc/get_error.c
@@ -0,0 +1,6 @@
+if (check_errno && sparc_regs.psr & PSR_C) {
+	tcp->u_rval = -1;
+	tcp->u_error = sparc_regs.u_regs[U_REG_O0];
+} else {
+	tcp->u_rval = sparc_regs.u_regs[U_REG_O0];
+}
diff --git a/linux/sparc/get_scno.c b/linux/sparc/get_scno.c
new file mode 100644
index 0000000..b190b6c
--- /dev/null
+++ b/linux/sparc/get_scno.c
@@ -0,0 +1 @@
+scno = sparc_regs.u_regs[U_REG_G1];
diff --git a/linux/sparc/get_syscall_args.c b/linux/sparc/get_syscall_args.c
new file mode 100644
index 0000000..14bce8f
--- /dev/null
+++ b/linux/sparc/get_syscall_args.c
@@ -0,0 +1,6 @@
+tcp->u_arg[0] = sparc_regs.u_regs[U_REG_O0 + 0];
+tcp->u_arg[1] = sparc_regs.u_regs[U_REG_O0 + 1];
+tcp->u_arg[2] = sparc_regs.u_regs[U_REG_O0 + 2];
+tcp->u_arg[3] = sparc_regs.u_regs[U_REG_O0 + 3];
+tcp->u_arg[4] = sparc_regs.u_regs[U_REG_O0 + 4];
+tcp->u_arg[5] = sparc_regs.u_regs[U_REG_O0 + 5];
diff --git a/linux/sparc/ioctlent1.h b/linux/sparc/ioctlent1.h
deleted file mode 100644
index 72efe42..0000000
--- a/linux/sparc/ioctlent1.h
+++ /dev/null
@@ -1,429 +0,0 @@
-{"DKIOCGGEOM", 0x401},
-{"DKIOCSGEOM", 0x402},
-{"DKIOCINFO", 0x403},
-{"DKIOCSAPART", 0x404},
-{"DKIOCGAPART", 0x405},
-{"DKIOCEJECT", 0x406},
-{"DKIOCLOCK", 0x407},
-{"DKIOCUNLOCK", 0x408},
-{"DKIOCGVTOC", 0x40b},
-{"DKIOCSVTOC", 0x40c},
-{"DKIOCSTATE", 0x40d},
-{"FDIOGCHAR", 0x433},
-{"FDIOSCHAR", 0x434},
-{"FDEJECT", 0x435},
-{"FDGETCHANGE", 0x436},
-{"FDGETDRIVECHAR", 0x437},
-{"FDSETDRIVECHAR", 0x438},
-{"FDGETSEARCH", 0x439},
-{"FDSETSEARCH", 0x43a},
-{"FDIOCMD", 0x43b},
-{"FDRAW", 0x446},
-{"FDDEFGEOCHAR", 0x456},
-{"HDKIOCSTYPE", 0x465},
-{"HDKIOCGTYPE", 0x466},
-{"HDKIOCSBAD", 0x467},
-{"HDKIOCGBAD", 0x468},
-{"HDKIOCSCMD", 0x469},
-{"HDKIOCGDIAG", 0x46a},
-{"CDROMPAUSE", 0x497},
-{"CDROMRESUME", 0x498},
-{"CDROMPLAYMSF", 0x499},
-{"CDROMPLAYTRKIND", 0x49a},
-{"CDROMREADTOCHDR", 0x49b},
-{"CDROMREADTOCENTRY", 0x49c},
-{"CDROMSTOP", 0x49d},
-{"CDROMSTART", 0x49e},
-{"CDROMEJECT", 0x49f},
-{"CDROMVOLCTRL", 0x4a0},
-{"CDROMSUBCHNL", 0x4a1},
-{"CDROMREADMODE2", 0x4a2},
-{"CDROMREADMODE1", 0x4a3},
-{"CDROMREADOFFSET", 0x4a4},
-{"CDROMGBLKMODE", 0x4a5},
-{"CDROMSBLKMODE", 0x4a6},
-{"CDROMCDDA", 0x4a7},
-{"CDROMCDXA", 0x4a8},
-{"CDROMSUBCODE", 0x4a9},
-{"CDROMGDRVSPEED", 0x4aa},
-{"CDROMSDRVSPEED", 0x4ab},
-{"USCSICMD", 0x4c9},
-{"SBIOCSTIME", 0x4201},
-{"SBIOCGTIME", 0x4202},
-{"SBIOCCTIME", 0x4203},
-{"SBIOCSCHUNK", 0x4204},
-{"SBIOCGCHUNK", 0x4205},
-{"SBIOCSSNAP", 0x4206},
-{"SBIOCGSNAP", 0x4207},
-{"SBIOCSFLAGS", 0x4208},
-{"SBIOCGFLAGS", 0x4209},
-{"LDOPEN", 0x4400},
-{"LDCLOSE", 0x4401},
-{"DLIOCRAW", 0x4401},
-{"SAD_SAP", 0x4401},
-{"LDCHG", 0x4402},
-{"SAD_GAP", 0x4402},
-{"SAD_VML", 0x4403},
-{"LDGETT", 0x4408},
-{"LDSETT", 0x4409},
-{"DL_IOC_HDR_INFO", 0x440a},
-{"LDSMAP", 0x446e},
-{"LDGMAP", 0x446f},
-{"LDNMAP", 0x4470},
-{"LDEMAP", 0x4471},
-{"LDDMAP", 0x4472},
-{"FBIOGTYPE", 0x4600},
-{"FBIOGINFO", 0x4602},
-{"FBIOPUTCMAP", 0x4603},
-{"FBIOGETCMAP", 0x4604},
-{"FBIOSATTR", 0x4605},
-{"FBIOGATTR", 0x4606},
-{"FBIOSVIDEO", 0x4607},
-{"FBIOGVIDEO", 0x4608},
-{"FBIOVERTICAL", 0x4609},
-{"GRABPAGEALLOC", 0x460a},
-{"GRABPAGEFREE", 0x460b},
-{"GRABATTACH", 0x460c},
-{"FBIOGPLNGRP", 0x460d},
-{"FBIOGCMSIZE", 0x460e},
-{"FBIOSCMSIZE", 0x460f},
-{"FBIOSCMS", 0x4610},
-{"FBIOAVAILPLNGRP", 0x4611},
-{"FBIODBLGINFO", 0x4612},
-{"FBIODBLSINFO", 0x4613},
-{"FBIOSWINFD", 0x4614},
-{"FBIOSAVWINFD", 0x4615},
-{"FBIORESWINFD", 0x4616},
-{"FBIOSRWINFD", 0x4617},
-{"VIS_SETCURSOR", 0x4618},
-{"FBIOSCURSOR", 0x4618},
-{"FBIOGCURSOR", 0x4619},
-{"VIS_GETCURSOR", 0x4619},
-{"FBIOSCURPOS", 0x461a},
-{"VIS_MOVECURSOR", 0x461a},
-{"FBIOGCURPOS", 0x461b},
-{"VIS_GETCURSORPOS", 0x461b},
-{"FBIOGCURMAX", 0x461c},
-{"GRABLOCKINFO", 0x461d},
-{"FBIO_WID_ALLOC", 0x461e},
-{"FBIO_WID_FREE", 0x461f},
-{"FBIO_WID_PUT", 0x4620},
-{"FBIO_WID_GET", 0x4621},
-{"FBIO_DEVID", 0x4622},
-{"FBIO_U_RST", 0x4623},
-{"FBIO_FULLSCREEN_ELIMINATION_GROUPS", 0x4624},
-{"FBIO_WID_DBL_SET", 0x4625},
-{"FBIOVRTOFFSET", 0x4626},
-{"FBIOGXINFO", 0x4627},
-{"FBIOMONINFO", 0x4628},
-{"FBIOPUTCMAPI", 0x4629},
-{"FBIOGETCMAPI", 0x462a},
-{"FBIO_ASSIGNWID", 0x462b},
-{"FBIO_STEREO", 0x462c},
-{"GP1IO_PUT_INFO", 0x4700},
-{"GP1IO_GET_STATIC_BLOCK", 0x4701},
-{"GP1IO_FREE_STATIC_BLOCK", 0x4702},
-{"GP1IO_GET_GBUFFER_STATE", 0x4703},
-{"GP1IO_CHK_GP", 0x4704},
-{"GP1IO_GET_RESTART_COUNT", 0x4705},
-{"GP1IO_REDIRECT_DEVFB", 0x4706},
-{"GP1IO_GET_REQDEV", 0x4707},
-{"GP1IO_GET_TRUMINORDEV", 0x4708},
-{"GP1IO_CHK_FOR_GBUFFER", 0x4709},
-{"GP1IO_SET_USING_GBUFFER", 0x470a},
-{"GP1IO_INFO_STATIC_BLOCK", 0x470b},
-{"O_SI_GETUDATA", 0x4965},
-{"SI_SHUTDOWN", 0x4966},
-{"SI_LISTEN", 0x4967},
-{"SI_SETMYNAME", 0x4968},
-{"SI_SETPEERNAME", 0x4969},
-{"SI_GETINTRANSIT", 0x496a},
-{"SI_SOCKPARAMS", 0x496d},
-{"SI_GETUDATA", 0x496e},
-{"I_TRCLOG", 0x4c01},
-{"I_ERRLOG", 0x4c02},
-{"I_CONSLOG", 0x4c03},
-{"MDI_RESET", 0x4d01},
-{"MDI_GET_CFGINFO", 0x4d02},
-{"MDI_SET_PIXELMODE", 0x4d03},
-{"MDI_SET_COUNTERS", 0x4d04},
-{"MDI_SET_PPR", 0x4d05},
-{"MDI_VRT_CNTL", 0x4d06},
-{"MDI_SET_CLUT", 0x4d07},
-{"MDI_GET_CLUT", 0x4d08},
-{"MDI_SET_XLUT", 0x4d09},
-{"MDI_GET_XLUT", 0x4d0a},
-{"MDI_GAMMA_CORRECT", 0x4d0b},
-{"MDI_SET_GAMMALUT", 0x4d0c},
-{"MDI_GET_GAMMALUT", 0x4d0d},
-{"MDI_SET_DEGAMMALUT", 0x4d0e},
-{"MDI_GET_DEGAMMALUT", 0x4d0f},
-{"MDI_GET_BUFFER_INFO", 0x4d10},
-{"MDI_SET_CURSOR", 0x4d11},
-{"MDI_GET_DIAGINFO", 0x4d12},
-{"MDI_SET_RESOLUTION", 0x4d13},
-{"SET_MONITOR_POWER", 0x4d14},
-{"OPROMGETBOOTARGS", 0x4f0c},
-{"PFIOCSETF", 0x5001},
-{"I_NREAD", 0x5301},
-{"I_PUSH", 0x5302},
-{"I_POP", 0x5303},
-{"I_LOOK", 0x5304},
-{"I_FLUSH", 0x5305},
-{"I_SRDOPT", 0x5306},
-{"I_GRDOPT", 0x5307},
-{"I_STR", 0x5308},
-{"I_SETSIG", 0x5309},
-{"I_GETSIG", 0x530a},
-{"I_FIND", 0x530b},
-{"I_LINK", 0x530c},
-{"I_UNLINK", 0x530d},
-{"I_RECVFD", 0x530e},
-{"I_PEEK", 0x530f},
-{"I_FDINSERT", 0x5310},
-{"I_SENDFD", 0x5311},
-{"I_SWROPT", 0x5313},
-{"I_GWROPT", 0x5314},
-{"I_LIST", 0x5315},
-{"I_PLINK", 0x5316},
-{"I_PUNLINK", 0x5317},
-{"I_SETEV", 0x5318},
-{"I_GETEV", 0x5319},
-{"I_STREV", 0x531a},
-{"I_UNSTREV", 0x531b},
-{"I_FLUSHBAND", 0x531c},
-{"I_CKBAND", 0x531d},
-{"I_GETBAND", 0x531e},
-{"I_ATMARK", 0x531f},
-{"I_SETCLTIME", 0x5320},
-{"I_GETCLTIME", 0x5321},
-{"I_CANPUT", 0x5322},
-{"TCGETA", 0x5401},
-{"TCSETA", 0x5402},
-{"TCSETAW", 0x5403},
-{"TCSETAF", 0x5404},
-{"TCSBRK", 0x5405},
-{"TCXONC", 0x5406},
-{"TCFLSH", 0x5407},
-{"TIOCKBON", 0x5408},
-{"TIOCKBOF", 0x5409},
-{"KBENABLED", 0x540a},
-{"TCGETS", 0x540d},
-{"TCSETS", 0x540e},
-{"TCSANOW", 0x540e},
-{"TCSADRAIN", 0x540f},
-{"TCSETSW", 0x540f},
-{"TCSAFLUSH", 0x5410},
-{"TCSETSF", 0x5410},
-{"TCDSET", 0x5420},
-{"TCDSET", 0x5420},
-{"RTS_TOG", 0x5421},
-{"TIOCSWINSZ", 0x5467},
-{"TIOCSWINSZ", 0x5467},
-{"TIOCGWINSZ", 0x5468},
-{"TIOCGWINSZ", 0x5468},
-{"TIOCGSOFTCAR", 0x5469},
-{"TIOCSSOFTCAR", 0x546a},
-{"TI_GETINFO", 0x548c},
-{"TI_OPTMGMT", 0x548d},
-{"TI_BIND", 0x548e},
-{"TI_UNBIND", 0x548f},
-{"TI_GETMYNAME", 0x5490},
-{"TI_GETPEERNAME", 0x5491},
-{"TI_SETMYNAME", 0x5492},
-{"TI_SETPEERNAME", 0x5493},
-{"TCGETX", 0x5801},
-{"TCSETX", 0x5802},
-{"TCSETXW", 0x5803},
-{"TCSETXF", 0x5804},
-{"DIOCGETC", 0x6401},
-{"DIOCGETB", 0x6402},
-{"DIOCSETE", 0x6403},
-{"DIOCGETP", 0x6408},
-{"DIOCSETP", 0x6409},
-{"JBOOT", 0x6a01},
-{"JTERM", 0x6a02},
-{"JMPX", 0x6a03},
-{"JWINSIZE", 0x6a05},
-{"JZOMBOOT", 0x6a07},
-{"JAGENT", 0x6a09},
-{"JTRUN", 0x6a0a},
-{"JXTPROTO", 0x6a0b},
-{"KIOCTRANS", 0x6b00},
-{"KIOCSETKEY", 0x6b01},
-{"KIOCGETKEY", 0x6b02},
-{"KIOCGTRANS", 0x6b05},
-{"KIOCTRANSABLE", 0x6b06},
-{"KIOCGTRANSABLE", 0x6b07},
-{"KIOCCMD", 0x6b08},
-{"KIOCTYPE", 0x6b09},
-{"KIOCSDIRECT", 0x6b0a},
-{"KIOCGDIRECT", 0x6b0b},
-{"KIOCSKEY", 0x6b0c},
-{"KIOCGKEY", 0x6b0d},
-{"KIOCSLED", 0x6b0e},
-{"KIOCGLED", 0x6b0f},
-{"KIOCSCOMPAT", 0x6b10},
-{"KIOCGCOMPAT", 0x6b11},
-{"KIOCLAYOUT", 0x6b14},
-{"LIOCGETP", 0x6c01},
-{"LIOCSETP", 0x6c02},
-{"LIOCGETS", 0x6c05},
-{"LIOCSETS", 0x6c06},
-{"MTIOCTOP", 0x6d01},
-{"MSIOGETPARMS", 0x6d01},
-{"MSIOSETPARMS", 0x6d02},
-{"MTIOCGET", 0x6d02},
-{"MTIOCGETDRIVETYPE", 0x6d03},
-{"PIOCSTATUS", 0x7101},
-{"PIOCSTOP", 0x7102},
-{"PIOCWSTOP", 0x7103},
-{"PIOCRUN", 0x7104},
-{"PIOCGTRACE", 0x7105},
-{"PIOCSTRACE", 0x7106},
-{"PIOCSSIG", 0x7107},
-{"PIOCKILL", 0x7108},
-{"PIOCUNKILL", 0x7109},
-{"PIOCGHOLD", 0x710a},
-{"PIOCSHOLD", 0x710b},
-{"PIOCMAXSIG", 0x710c},
-{"PIOCACTION", 0x710d},
-{"PIOCGFAULT", 0x710e},
-{"PIOCSFAULT", 0x710f},
-{"PIOCCFAULT", 0x7110},
-{"PIOCGENTRY", 0x7111},
-{"PIOCSENTRY", 0x7112},
-{"PIOCGEXIT", 0x7113},
-{"PIOCSEXIT", 0x7114},
-{"PIOCSFORK", 0x7115},
-{"PIOCRFORK", 0x7116},
-{"PIOCSRLC", 0x7117},
-{"PIOCRRLC", 0x7118},
-{"PIOCGREG", 0x7119},
-{"PIOCSREG", 0x711a},
-{"PIOCGFPREG", 0x711b},
-{"PIOCSFPREG", 0x711c},
-{"PIOCNICE", 0x711d},
-{"PIOCPSINFO", 0x711e},
-{"PIOCNMAP", 0x711f},
-{"PIOCMAP", 0x7120},
-{"PIOCOPENM", 0x7121},
-{"PIOCCRED", 0x7122},
-{"PIOCGROUPS", 0x7123},
-{"PIOCGETPR", 0x7124},
-{"PIOCGETU", 0x7125},
-{"PIOCSET", 0x7126},
-{"PIOCRESET", 0x7127},
-{"PIOCNWATCH", 0x7128},
-{"PIOCGWATCH", 0x7129},
-{"PIOCSWATCH", 0x712a},
-{"PIOCUSAGE", 0x712b},
-{"PIOCOPENPD", 0x712c},
-{"PIOCLWPIDS", 0x712d},
-{"PIOCOPENLWP", 0x712e},
-{"PIOCLSTATUS", 0x712f},
-{"PIOCLUSAGE", 0x7130},
-{"PIOCNAUXV", 0x7131},
-{"PIOCAUXV", 0x7132},
-{"PIOCGWIN", 0x7165},
-{"TIOCGETD", 0x7400},
-{"TIOCGETD", 0x7400},
-{"TIOCSETD", 0x7401},
-{"TIOCSETD", 0x7401},
-{"TIOCHPCL", 0x7402},
-{"TIOCHPCL", 0x7402},
-{"TIOCGETP", 0x7408},
-{"TIOCGETP", 0x7408},
-{"TIOCSETP", 0x7409},
-{"TIOCSETP", 0x7409},
-{"TIOCSETN", 0x740a},
-{"TIOCSETN", 0x740a},
-{"TIOCEXCL", 0x740d},
-{"TIOCEXCL", 0x740d},
-{"TIOCNXCL", 0x740e},
-{"TIOCNXCL", 0x740e},
-{"TIOCFLUSH", 0x7410},
-{"TIOCFLUSH", 0x7410},
-{"TIOCSETC", 0x7411},
-{"TIOCSETC", 0x7411},
-{"TIOCGETC", 0x7412},
-{"TIOCGETC", 0x7412},
-{"TIOCGPGRP", 0x7414},
-{"TIOCSPGRP", 0x7415},
-{"TIOCGSID", 0x7416},
-{"TIOCSTI", 0x7417},
-{"TIOCSSID", 0x7418},
-{"TIOCMSET", 0x741a},
-{"TIOCMBIS", 0x741b},
-{"TIOCMBIC", 0x741c},
-{"TIOCMGET", 0x741d},
-{"TIOCREMOTE", 0x741e},
-{"TIOCREMOTE", 0x741e},
-{"TIOCSIGNAL", 0x741f},
-{"TIOCSTART", 0x746e},
-{"TIOCSTART", 0x746e},
-{"TIOCSTOP", 0x746f},
-{"TIOCSTOP", 0x746f},
-{"TIOCNOTTY", 0x7471},
-{"TIOCNOTTY", 0x7471},
-{"TIOCOUTQ", 0x7473},
-{"TIOCOUTQ", 0x7473},
-{"TIOCGLTC", 0x7474},
-{"TIOCGLTC", 0x7474},
-{"TIOCSLTC", 0x7475},
-{"TIOCSLTC", 0x7475},
-{"TIOCCDTR", 0x7478},
-{"TIOCCDTR", 0x7478},
-{"TIOCSDTR", 0x7479},
-{"TIOCSDTR", 0x7479},
-{"TIOCCBRK", 0x747a},
-{"TIOCCBRK", 0x747a},
-{"TIOCSBRK", 0x747b},
-{"TIOCSBRK", 0x747b},
-{"TIOCLGET", 0x747c},
-{"TIOCLGET", 0x747c},
-{"TIOCLSET", 0x747d},
-{"TIOCLSET", 0x747d},
-{"TIOCLBIC", 0x747e},
-{"TIOCLBIC", 0x747e},
-{"TIOCLBIS", 0x747f},
-{"TIOCLBIS", 0x747f},
-{"VOLIOCMAP", 0x7601},
-{"VUIDSFORMAT", 0x7601},
-{"VUIDSFORMAT", 0x7601},
-{"VUIDGFORMAT", 0x7602},
-{"VUIDGFORMAT", 0x7602},
-{"VOLIOCUNMAP", 0x7602},
-{"VOLIOCEVENT", 0x7603},
-{"VUIDSADDR", 0x7603},
-{"VUIDSADDR", 0x7603},
-{"VUIDGADDR", 0x7604},
-{"VUIDGADDR", 0x7604},
-{"VOLIOCEJECT", 0x7604},
-{"VOLIOCCHECK", 0x7605},
-{"VOLIOCINUSE", 0x7606},
-{"VOLIOCDGATTR", 0x7607},
-{"VOLIOCDSATTR", 0x7608},
-{"VOLIOCDCHECK", 0x7609},
-{"VOLIOCCANCEL", 0x760a},
-{"VOLIOCINFO", 0x760b},
-{"VOLIOCSATTR", 0x760c},
-{"VOLIOCGATTR", 0x760d},
-{"VOLIOCDINUSE", 0x760e},
-{"VOLIOCDAEMON", 0x760f},
-{"VOLIOCFLAGS", 0x7610},
-{"VOLIOCEXTRA4", 0x7611},
-{"VOLIOCEXTRA5", 0x7612},
-{"VOLIOCEXTRA6", 0x7613},
-{"VOLIOCEXTRA7", 0x7614},
-{"S_IOCGETMODE", 0x7a01},
-{"S_IOCSETMODE", 0x7a02},
-{"S_IOCGETSTATS", 0x7a03},
-{"S_IOCCLRSTATS", 0x7a04},
-{"S_IOCGETSPEED", 0x7a05},
-{"S_IOCGETMRU", 0x7a06},
-{"S_IOCSETMRU", 0x7a07},
-{"S_IOCGETMTU", 0x7a08},
-{"S_IOCSETMTU", 0x7a09},
-{"S_IOCGETMCTL", 0x7a0a},
-{"TL_IOC_CREDOPT", 0x544c01},
diff --git a/linux/sparc/print_pc.c b/linux/sparc/print_pc.c
new file mode 100644
index 0000000..683e3b1
--- /dev/null
+++ b/linux/sparc/print_pc.c
@@ -0,0 +1 @@
+tprintf(fmt, sparc_regs.pc);
diff --git a/linux/sparc/signalent1.h b/linux/sparc/signalent1.h
deleted file mode 100644
index 58869a5..0000000
--- a/linux/sparc/signalent1.h
+++ /dev/null
@@ -1,36 +0,0 @@
-	"SIG_0",	/* 0 */
-	"SIGHUP",	/* 1 */
-	"SIGINT",	/* 2 */
-	"SIGQUIT",	/* 3 */
-	"SIGILL",	/* 4 */
-	"SIGTRAP",	/* 5 */
-	"SIGABRT",	/* 6 */
-	"SIGEMT",	/* 7 */
-	"SIGFPE",	/* 8 */
-	"SIGKILL",	/* 9 */
-	"SIGBUS",	/* 10 */
-	"SIGSEGV",	/* 11 */
-	"SIGSYS",	/* 12 */
-	"SIGPIPE",	/* 13 */
-	"SIGALRM",	/* 14 */
-	"SIGTERM",	/* 15 */
-	"SIGUSR1",	/* 16 */
-	"SIGUSR2",	/* 17 */
-	"SIGCHLD",	/* 18 */
-	"SIGPWR",	/* 19 */
-	"SIGWINCH",	/* 20 */
-	"SIGURG",	/* 21 */
-	"SIGPOLL",	/* 22 */
-	"SIGSTOP",	/* 23 */
-	"SIGTSTP",	/* 24 */
-	"SIGCONT",	/* 25 */
-	"SIGTTIN",	/* 26 */
-	"SIGTTOU",	/* 27 */
-	"SIGVTALRM",	/* 28 */
-	"SIGPROF",	/* 29 */
-	"SIGXCPU",	/* 30 */
-	"SIGXFSZ",	/* 31 */
-	"SIGWAITING",	/* 32 */
-	"SIGLWP",	/* 33 */
-	"SIGFREEZE",	/* 34 */
-	"SIGTHAW",	/* 35 */
diff --git a/linux/sparc/syscall1.h b/linux/sparc/syscall1.h
deleted file mode 100644
index 6f30b74..0000000
--- a/linux/sparc/syscall1.h
+++ /dev/null
@@ -1,498 +0,0 @@
-/*
- * Copyright (c) 1993, 1994, 1995 Rick Sladkey <jrs@world.std.com>
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- * 3. The name of the author may not be used to endorse or promote products
- *    derived from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#define	SOLARIS_syscall	0
-#define	SOLARIS_exit	1
-#define	SOLARIS_fork	2
-#define	SOLARIS_read	3
-#define	SOLARIS_write	4
-#define	SOLARIS_open	5
-#define	SOLARIS_close	6
-#define	SOLARIS_wait	7
-#define	SOLARIS_creat	8
-#define	SOLARIS_link	9
-#define	SOLARIS_unlink	10
-#define	SOLARIS_exec	11
-#define	SOLARIS_chdir	12
-#define	SOLARIS_time	13
-#define	SOLARIS_mknod	14
-#define	SOLARIS_chmod	15
-#define	SOLARIS_chown	16
-#define	SOLARIS_brk		17
-#define	SOLARIS_stat	18
-#define	SOLARIS_lseek	19
-#define	SOLARIS_getpid	20
-#define	SOLARIS_mount	21
-#define	SOLARIS_umount	22
-#define	SOLARIS_setuid	23
-#define	SOLARIS_getuid	24
-#define	SOLARIS_stime	25
-#define	SOLARIS_ptrace	26
-#define	SOLARIS_alarm	27
-#define	SOLARIS_fstat	28
-#define	SOLARIS_pause	29
-#define	SOLARIS_utime	30
-#define	SOLARIS_stty	31
-#define	SOLARIS_gtty	32
-#define	SOLARIS_access	33
-#define	SOLARIS_nice	34
-#define	SOLARIS_statfs	35
-#define	SOLARIS_sync	36
-#define	SOLARIS_kill	37
-#define	SOLARIS_fstatfs	38
-#define	SOLARIS_pgrpsys	39
-#define	SOLARIS_xenix	40
-#define	SOLARIS_dup		41
-#define	SOLARIS_pipe	42
-#define	SOLARIS_times	43
-#define	SOLARIS_profil	44
-#define	SOLARIS_plock	45
-#define	SOLARIS_setgid	46
-#define	SOLARIS_getgid	47
-#define	SOLARIS_signal	48
-#define	SOLARIS_msgsys	49
-#define	SOLARIS_syssun	50
-#define	SOLARIS_acct	51
-#define	SOLARIS_shmsys	52
-#define	SOLARIS_semsys	53
-#define	SOLARIS_ioctl	54
-#define	SOLARIS_uadmin	55
-#define	SOLARIS_utssys	57
-#define	SOLARIS_fdsync	58
-#define	SOLARIS_execve	59
-#define	SOLARIS_umask	60
-#define	SOLARIS_chroot	61
-#define	SOLARIS_fcntl	62
-#define	SOLARIS_ulimit	63
-#define	SOLARIS_rmdir	79
-#define	SOLARIS_mkdir	80
-#define	SOLARIS_getdents	81
-#define	SOLARIS_sysfs	84
-#define	SOLARIS_getmsg	85
-#define	SOLARIS_putmsg	86
-#define	SOLARIS_poll	87
-#define	SOLARIS_lstat	88
-#define	SOLARIS_symlink	89
-#define	SOLARIS_readlink	90
-#define	SOLARIS_setgroups	91
-#define	SOLARIS_getgroups	92
-#define	SOLARIS_fchmod	93
-#define	SOLARIS_fchown	94
-#define	SOLARIS_sigprocmask	95
-#define	SOLARIS_sigsuspend	96
-#define	SOLARIS_sigaltstack	97
-#define	SOLARIS_sigaction	98
-#define	SOLARIS_sigpending	99
-#define	SOLARIS_context	100
-#define	SOLARIS_evsys	101
-#define	SOLARIS_evtrapret	102
-#define	SOLARIS_statvfs	103
-#define	SOLARIS_fstatvfs	104
-#define	SOLARIS_nfssys	106
-#define	SOLARIS_waitsys	107
-#define	SOLARIS_sigsendsys	108
-#define	SOLARIS_hrtsys	109
-#define	SOLARIS_acancel	110
-#define	SOLARIS_async	111
-#define	SOLARIS_priocntlsys	112
-#define	SOLARIS_pathconf	113
-#define	SOLARIS_mincore	114
-#define	SOLARIS_mmap	115
-#define	SOLARIS_mprotect	116
-#define	SOLARIS_munmap	117
-#define	SOLARIS_fpathconf	118
-#define	SOLARIS_vfork	119
-#define	SOLARIS_fchdir	120
-#define	SOLARIS_readv	121
-#define	SOLARIS_writev	122
-#define	SOLARIS_xstat	123
-#define	SOLARIS_lxstat	124
-#define	SOLARIS_fxstat	125
-#define	SOLARIS_xmknod	126
-#define	SOLARIS_clocal	127
-#define	SOLARIS_setrlimit	128
-#define	SOLARIS_getrlimit	129
-#define	SOLARIS_lchown	130
-#define	SOLARIS_memcntl	131
-#define	SOLARIS_getpmsg	132
-#define	SOLARIS_putpmsg	133
-#define	SOLARIS_rename	134
-#define	SOLARIS_uname	135
-#define	SOLARIS_setegid	136
-#define	SOLARIS_sysconfig	137
-#define	SOLARIS_adjtime	138
-#define	SOLARIS_systeminfo	139
-#define	SOLARIS_seteuid	141
-#define	SOLARIS_vtrace	142
-#define	SOLARIS_fork1	143
-#define	SOLARIS_sigtimedwait	144
-#define	SOLARIS_lwp_info	145
-#define	SOLARIS_yield	146
-#define	SOLARIS_lwp_sema_wait	147
-#define	SOLARIS_lwp_sema_post	148
-#define	SOLARIS_modctl	152
-#define	SOLARIS_fchroot	153
-#define	SOLARIS_utimes	154
-#define	SOLARIS_vhangup	155
-#define	SOLARIS_gettimeofday	156
-#define	SOLARIS_getitimer		157
-#define	SOLARIS_setitimer		158
-#define	SOLARIS_lwp_create		159
-#define	SOLARIS_lwp_exit		160
-#define	SOLARIS_lwp_suspend		161
-#define	SOLARIS_lwp_continue	162
-#define	SOLARIS_lwp_kill		163
-#define	SOLARIS_lwp_self		164
-#define	SOLARIS_lwp_setprivate	165
-#define	SOLARIS_lwp_getprivate	166
-#define	SOLARIS_lwp_wait		167
-#define	SOLARIS_lwp_mutex_unlock	168
-#define	SOLARIS_lwp_mutex_lock	169
-#define	SOLARIS_lwp_cond_wait	170
-#define	SOLARIS_lwp_cond_signal	171
-#define	SOLARIS_lwp_cond_broadcast	172
-#define	SOLARIS_pread		173
-#define	SOLARIS_pwrite		174
-#define	SOLARIS_llseek		175
-#define	SOLARIS_inst_sync		176
-#define	SOLARIS_kaio		178
-#define	SOLARIS_tsolsys		184
-#define	SOLARIS_acl			185
-#define	SOLARIS_auditsys		186
-#define	SOLARIS_processor_bind	187
-#define	SOLARIS_processor_info	188
-#define	SOLARIS_p_online		189
-#define	SOLARIS_sigqueue		190
-#define	SOLARIS_clock_gettime	191
-#define	SOLARIS_clock_settime	192
-#define	SOLARIS_clock_getres	193
-#define	SOLARIS_timer_create	194
-#define	SOLARIS_timer_delete	195
-#define	SOLARIS_timer_settime	196
-#define	SOLARIS_timer_gettime	197
-#define	SOLARIS_timer_getoverrun	198
-#define	SOLARIS_nanosleep		199
-#define	SOLARIS_facl		200
-#define	SOLARIS_door		201
-#define	SOLARIS_setreuid		202
-#define	SOLARIS_setregid		203
-#define	SOLARIS_signotifywait	210
-#define	SOLARIS_lwp_sigredirect	211
-#define	SOLARIS_lwp_alarm		212
-
-#include "dummy2.h"
-
-extern int solaris_syscall();
-extern int solaris_exit();
-extern int solaris_fork();
-extern int solaris_read();
-extern int solaris_write();
-extern int solaris_open();
-extern int solaris_close();
-extern int solaris_wait();
-extern int solaris_creat();
-extern int solaris_link();
-extern int solaris_unlink();
-extern int solaris_exec();
-extern int solaris_chdir();
-extern int solaris_time();
-extern int solaris_mknod();
-extern int solaris_chmod();
-extern int solaris_chown();
-extern int solaris_brk();
-extern int solaris_stat();
-extern int solaris_lseek();
-extern int solaris_getpid();
-extern int solaris_mount();
-extern int solaris_umount();
-extern int solaris_setuid();
-extern int solaris_getuid();
-extern int solaris_stime();
-extern int solaris_ptrace();
-extern int solaris_alarm();
-extern int solaris_fstat();
-extern int solaris_pause();
-extern int solaris_utime();
-extern int solaris_stty();
-extern int solaris_gtty();
-extern int solaris_access();
-extern int solaris_nice();
-extern int solaris_statfs();
-extern int solaris_sync();
-extern int solaris_kill();
-extern int solaris_fstatfs();
-extern int solaris_pgrpsys();
-extern int solaris_setpgrp();
-extern int solaris_xenix();
-extern int solaris_syssgi();
-extern int solaris_dup();
-extern int solaris_pipe();
-extern int solaris_times();
-extern int solaris_profil();
-extern int solaris_plock();
-extern int solaris_setgid();
-extern int solaris_getgid();
-extern int solaris_sigcall();
-extern int solaris_msgsys();
-extern int solaris_syssun();
-extern int solaris_sysi86();
-extern int solaris_sysmips();
-extern int solaris_sysmachine();
-extern int solaris_acct();
-extern int solaris_shmsys();
-extern int solaris_semsys();
-extern int solaris_ioctl();
-extern int solaris_uadmin();
-extern int solaris_utssys();
-extern int solaris_fdsync();
-extern int solaris_execve();
-extern int solaris_umask();
-extern int solaris_chroot();
-extern int solaris_fcntl();
-extern int solaris_ulimit();
-extern int solaris_rmdir();
-extern int solaris_mkdir();
-extern int solaris_getdents();
-extern int solaris_sysfs();
-extern int solaris_getmsg();
-extern int solaris_putmsg();
-extern int solaris_poll();
-extern int solaris_lstat();
-extern int solaris_symlink();
-extern int solaris_readlink();
-extern int solaris_setgroups();
-extern int solaris_getgroups();
-extern int solaris_fchmod();
-extern int solaris_fchown();
-extern int solaris_sigprocmask();
-extern int solaris_sigsuspend();
-extern int solaris_sigaltstack();
-extern int solaris_sigaction();
-extern int solaris_spcall();
-extern int solaris_context();
-extern int solaris_evsys();
-extern int solaris_evtrapret();
-extern int solaris_statvfs();
-extern int solaris_fstatvfs();
-extern int solaris_nfssys();
-extern int solaris_waitid();
-extern int solaris_sigsendsys();
-extern int solaris_hrtsys();
-extern int solaris_acancel();
-extern int solaris_async();
-extern int solaris_priocntlsys();
-extern int solaris_pathconf();
-extern int solaris_mincore();
-extern int solaris_mmap();
-extern int solaris_mprotect();
-extern int solaris_munmap();
-extern int solaris_fpathconf();
-extern int solaris_vfork();
-extern int solaris_fchdir();
-extern int solaris_readv();
-extern int solaris_writev();
-extern int solaris_xstat();
-extern int solaris_lxstat();
-extern int solaris_fxstat();
-extern int solaris_xmknod();
-extern int solaris_clocal();
-extern int solaris_setrlimit();
-extern int solaris_getrlimit();
-extern int solaris_lchown();
-extern int solaris_memcntl();
-extern int solaris_getpmsg();
-extern int solaris_putpmsg();
-extern int solaris_rename();
-extern int solaris_uname();
-extern int solaris_setegid();
-extern int solaris_sysconfig();
-extern int solaris_adjtime();
-extern int solaris_sysinfo();
-extern int solaris_seteuid();
-extern int solaris_vtrace();
-extern int solaris_fork1();
-extern int solaris_sigtimedwait();
-extern int solaris_lwp_info();
-extern int solaris_yield();
-extern int solaris_lwp_sema_wait();
-extern int solaris_lwp_sema_post();
-extern int solaris_modctl();
-extern int solaris_fchroot();
-extern int solaris_utimes();
-extern int solaris_vhangup();
-extern int solaris_gettimeofday();
-extern int solaris_getitimer();
-extern int solaris_setitimer();
-extern int solaris_lwp_create();
-extern int solaris_lwp_exit();
-extern int solaris_lwp_suspend();
-extern int solaris_lwp_continue();
-extern int solaris_lwp_kill();
-extern int solaris_lwp_self();
-extern int solaris_lwp_setprivate();
-extern int solaris_lwp_getprivate();
-extern int solaris_lwp_wait();
-extern int solaris_lwp_mutex_unlock();
-extern int solaris_lwp_mutex_lock();
-extern int solaris_lwp_cond_wait();
-extern int solaris_lwp_cond_signal();
-extern int solaris_lwp_cond_broadcast();
-extern int solaris_pread();
-extern int solaris_pwrite();
-extern int solaris_llseek();
-extern int solaris_inst_sync();
-extern int solaris_auditsys();
-extern int solaris_processor_bind();
-extern int solaris_processor_info();
-extern int solaris_p_online();
-extern int solaris_sigqueue();
-extern int solaris_clock_gettime();
-extern int solaris_clock_settime();
-extern int solaris_clock_getres();
-extern int solaris_timer_create();
-extern int solaris_timer_delete();
-extern int solaris_timer_settime();
-extern int solaris_timer_gettime();
-extern int solaris_timer_getoverrun();
-extern int solaris_nanosleep();
-
-/* solaris_pgrpsys subcalls */
-
-extern int solaris_getpgrp(), solaris_setpgrp(), solaris_getsid();
-extern int solaris_setsid(), solaris_getpgid(), solaris_setpgid();
-
-#define SOLARIS_pgrpsys_subcall	300
-#define SOLARIS_getpgrp		(SOLARIS_pgrpsys_subcall + 0)
-#define SOLARIS_setpgrp		(SOLARIS_pgrpsys_subcall + 1)
-#define SOLARIS_getsid		(SOLARIS_pgrpsys_subcall + 2)
-#define SOLARIS_setsid		(SOLARIS_pgrpsys_subcall + 3)
-#define SOLARIS_getpgid		(SOLARIS_pgrpsys_subcall + 4)
-#define SOLARIS_setpgid		(SOLARIS_pgrpsys_subcall + 5)
-
-#define SOLARIS_pgrpsys_nsubcalls	6
-
-/* solaris_sigcall subcalls */
-
-#undef SOLARIS_signal
-#define SOLARIS_sigcall		48
-
-extern int solaris_signal(), solaris_sigset(), solaris_sighold();
-extern int solaris_sigrelse(), solaris_sigignore(), solaris_sigpause();
-
-#define SOLARIS_sigcall_subcall	310
-#define SOLARIS_signal		(SOLARIS_sigcall_subcall + 0)
-#define SOLARIS_sigset		(SOLARIS_sigcall_subcall + 1)
-#define SOLARIS_sighold		(SOLARIS_sigcall_subcall + 2)
-#define SOLARIS_sigrelse		(SOLARIS_sigcall_subcall + 3)
-#define SOLARIS_sigignore		(SOLARIS_sigcall_subcall + 4)
-#define SOLARIS_sigpause		(SOLARIS_sigcall_subcall + 5)
-
-#define SOLARIS_sigcall_nsubcalls	6
-
-/* msgsys subcalls */
-
-extern int solaris_msgget(), solaris_msgctl(), solaris_msgrcv(), solaris_msgsnd();
-
-#define SOLARIS_msgsys_subcall	320
-#define SOLARIS_msgget		(SOLARIS_msgsys_subcall + 0)
-#define SOLARIS_msgctl		(SOLARIS_msgsys_subcall + 1)
-#define SOLARIS_msgrcv		(SOLARIS_msgsys_subcall + 2)
-#define SOLARIS_msgsnd		(SOLARIS_msgsys_subcall + 3)
-
-#define SOLARIS_msgsys_nsubcalls	4
-
-/* shmsys subcalls */
-
-extern int solaris_shmat(), solaris_shmctl(), solaris_shmdt(), solaris_shmget();
-
-#define SOLARIS_shmsys_subcall	330
-#define SOLARIS_shmat		(SOLARIS_shmsys_subcall + 0)
-#define SOLARIS_shmctl		(SOLARIS_shmsys_subcall + 1)
-#define SOLARIS_shmdt		(SOLARIS_shmsys_subcall + 2)
-#define SOLARIS_shmget		(SOLARIS_shmsys_subcall + 3)
-
-#define SOLARIS_shmsys_nsubcalls	4
-
-/* semsys subcalls */
-
-extern int solaris_semctl(), solaris_semget(), solaris_semop();
-
-#define SOLARIS_semsys_subcall	340
-#define SOLARIS_semctl		(SOLARIS_semsys_subcall + 0)
-#define SOLARIS_semget		(SOLARIS_semsys_subcall + 1)
-#define SOLARIS_semop		(SOLARIS_semsys_subcall + 2)
-
-#define SOLARIS_semsys_nsubcalls	3
-
-/* utssys subcalls */
-
-extern int solaris_olduname(), solaris_ustat(), solaris_fusers();
-
-#define SOLARIS_utssys_subcall	350
-
-#define SOLARIS_olduname		(SOLARIS_utssys_subcall + 0)
-				/* 1 is unused */
-#define SOLARIS_ustat		(SOLARIS_utssys_subcall + 2)
-#define SOLARIS_fusers		(SOLARIS_utssys_subcall + 3)
-
-#define SOLARIS_utssys_nsubcalls	4
-
-/* sysfs subcalls */
-
-extern int solaris_sysfs1(), solaris_sysfs2(), solaris_sysfs3();
-
-#define SOLARIS_sysfs_subcall	360
-				/* 0 is unused */
-#define SOLARIS_sysfs1		(SOLARIS_sysfs_subcall + 1)
-#define SOLARIS_sysfs2		(SOLARIS_sysfs_subcall + 2)
-#define SOLARIS_sysfs3		(SOLARIS_sysfs_subcall + 3)
-
-#define SOLARIS_sysfs_nsubcalls	4
-
-/* solaris_spcall subcalls */
-
-#undef SOLARIS_sigpending
-#define SOLARIS_spcall		99
-
-extern int solaris_sigpending(), solaris_sigfillset();
-
-#define SOLARIS_spcall_subcall	370
-				/* 0 is unused */
-#define SOLARIS_sigpending		(SOLARIS_spcall_subcall + 1)
-#define SOLARIS_sigfillset		(SOLARIS_spcall_subcall + 2)
-
-#define SOLARIS_spcall_nsubcalls	3
-
-/* solaris_context subcalls */
-
-extern int solaris_getcontext(), solaris_setcontext();
-
-#define SOLARIS_context_subcall	380
-#define SOLARIS_getcontext		(SOLARIS_context_subcall + 0)
-#define SOLARIS_setcontext		(SOLARIS_context_subcall + 1)
-
-#define SOLARIS_context_nsubcalls	2
diff --git a/linux/sparc/syscallent.h b/linux/sparc/syscallent.h
index 3ccbd71..18fd65e 100644
--- a/linux/sparc/syscallent.h
+++ b/linux/sparc/syscallent.h
@@ -54,7 +54,7 @@
 [ 53] = { 0,	NF,		sys_getgid,			"getgid32"		},
 [ 54] = { 3,	TD,		sys_ioctl,			"ioctl"			},
 [ 55] = { 4,	0,		sys_reboot,			"reboot"		},
-[ 56] = { 6,	TD|TM|SI,	sys_mmap,			"mmap2"			},
+[ 56] = { 6,	TD|TM|SI,	sys_mmap_4koff,			"mmap2"			},
 [ 57] = { 2,	TF,		sys_symlink,			"symlink"		},
 [ 58] = { 3,	TF,		sys_readlink,			"readlink"		},
 [ 59] = { 3,	TF|TP|SE|SI,	sys_execve,			"execve"		},
diff --git a/linux/sparc/syscallent1.h b/linux/sparc/syscallent1.h
deleted file mode 100644
index 2e2805b..0000000
--- a/linux/sparc/syscallent1.h
+++ /dev/null
@@ -1,437 +0,0 @@
-/*
- * Copyright (c) 1993, 1994, 1995, 1996 Rick Sladkey <jrs@world.std.com>
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- * 3. The name of the author may not be used to endorse or promote products
- *    derived from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-	{ 6,	0,	solaris_syscall,	"syscall"	}, /* 0 */
-	{ 6,	TP,	solaris_exit,		"_exit"		}, /* 1 */
-	{ 6,	TP,	solaris_fork,		"fork"		}, /* 2 */
-	{ 6,	0,	solaris_read,		"read"		}, /* 3 */
-	{ 6,	0,	solaris_write,		"write"		}, /* 4 */
-	{ 6,	TF,	solaris_open,		"open"		}, /* 5 */
-	{ 6,	0,	solaris_close,		"close"		}, /* 6 */
-	{ 6,	TP,	solaris_wait,		"wait"		}, /* 7 */
-	{ 6,	TF,	solaris_creat,		"creat"		}, /* 8 */
-	{ 6,	TF,	solaris_link,		"link"		}, /* 9 */
-	{ 6,	TF,	solaris_unlink,		"unlink"	}, /* 10 */
-	{ 6,	TF|TP,	solaris_exec,		"exec"		}, /* 11 */
-	{ 6,	TF,	solaris_chdir,		"chdir"		}, /* 12 */
-	{ 6,	0,	solaris_time,		"time"		}, /* 13 */
-	{ 6,	TF,	solaris_mknod,		"mknod"		}, /* 14 */
-	{ 6,	TF,	solaris_chmod,		"chmod"		}, /* 15 */
-	{ 6,	TF,	solaris_chown,		"chown"		}, /* 16 */
-	{ 6,	0,	solaris_brk,		"brk"		}, /* 17 */
-	{ 6,	TF,	solaris_stat,		"stat"		}, /* 18 */
-	{ 6,	0,	solaris_lseek,		"lseek"		}, /* 19 */
-	{ 6,	0,	solaris_getpid,		"getpid"	}, /* 20 */
-	{ 6,	TF,	solaris_mount,		"mount"		}, /* 21 */
-	{ 6,	TF,	solaris_umount,		"umount"	}, /* 22 */
-	{ 6,	0,	solaris_setuid,		"setuid"	}, /* 23 */
-	{ 6,	0,	solaris_getuid,		"getuid"	}, /* 24 */
-	{ 6,	0,	solaris_stime,		"stime"		}, /* 25 */
-	{ 6,	0,	solaris_ptrace,		"ptrace"	}, /* 26 */
-	{ 6,	0,	solaris_alarm,		"alarm"		}, /* 27 */
-	{ 6,	0,	solaris_fstat,		"fstat"		}, /* 28 */
-	{ 6,	TS,	solaris_pause,		"pause"		}, /* 29 */
-	{ 6,	TF,	solaris_utime,		"utime"		}, /* 30 */
-	{ 6,	0,	solaris_stty,		"stty"		}, /* 31 */
-	{ 6,	0,	solaris_gtty,		"gtty"		}, /* 32 */
-	{ 6,	TF,	solaris_access,		"access"	}, /* 33 */
-	{ 6,	0,	solaris_nice,		"nice"		}, /* 34 */
-	{ 6,	TF,	solaris_statfs,		"statfs"	}, /* 35 */
-	{ 6,	0,	solaris_sync,		"sync"		}, /* 36 */
-	{ 6,	TS,	solaris_kill,		"kill"		}, /* 37 */
-	{ 6,	0,	solaris_fstatfs,	"fstatfs"	}, /* 38 */
-	{ 6,	0,	solaris_pgrpsys,	"pgrpsys"	}, /* 39 */
-	{ 6,	0,	solaris_xenix,		"xenix"		}, /* 40 */
-	{ 6,	0,	solaris_dup,		"dup"		}, /* 41 */
-	{ 6,	0,	solaris_pipe,		"pipe"		}, /* 42 */
-	{ 6,	0,	solaris_times,		"times"		}, /* 43 */
-	{ 6,	0,	solaris_profil,		"profil"	}, /* 44 */
-	{ 6,	0,	solaris_plock,		"plock"		}, /* 45 */
-	{ 6,	0,	solaris_setgid,		"setgid"	}, /* 46 */
-	{ 6,	0,	solaris_getgid,		"getgid"	}, /* 47 */
-	{ 6,	0,	solaris_sigcall,	"sigcall"	}, /* 48 */
-	{ 6,	TI,	solaris_msgsys,		"msgsys"	}, /* 49 */
-	{ 6,	0,	solaris_syssun,		"syssun"	}, /* 50 */
-	{ 6,	TF,	solaris_acct,		"acct"		}, /* 51 */
-	{ 6,	TI,	solaris_shmsys,		"shmsys"	}, /* 52 */
-	{ 6,	TI,	solaris_semsys,		"semsys"	}, /* 53 */
-	{ 6,	0,	solaris_ioctl,		"ioctl"		}, /* 54 */
-	{ 6,	0,	solaris_uadmin,		"uadmin"	}, /* 55 */
-	{ 6,	0,	solaris_sysmp,		"sysmp"		}, /* 56 */
-	{ 6,	0,	solaris_utssys,		"utssys"	}, /* 57 */
-	{ 6,	0,	solaris_fdsync,		"fdsync"	}, /* 58 */
-	{ 6,	TF|TP,	solaris_execve,		"execve"	}, /* 59 */
-	{ 6,	0,	solaris_umask,		"umask"		}, /* 60 */
-	{ 6,	TF,	solaris_chroot,		"chroot"	}, /* 61 */
-	{ 6,	0,	solaris_fcntl,		"fcntl"		}, /* 62 */
-	{ 6,	0,	solaris_ulimit,		"ulimit"	}, /* 63 */
-	{ 6,	0,	NULL,			NULL		}, /* 64 */
-	{ 6,	0,	NULL,			NULL		}, /* 65 */
-	{ 6,	0,	NULL,			NULL		}, /* 66 */
-	{ 6,	0,	NULL,			NULL		}, /* 67 */
-	{ 6,	0,	NULL,			NULL		}, /* 68 */
-	{ 6,	0,	NULL,			NULL		}, /* 69 */
-	{ 6,	0,	NULL,			NULL		}, /* 70 */
-	{ 6,	0,	NULL,			NULL		}, /* 71 */
-	{ 6,	0,	NULL,			NULL		}, /* 72 */
-	{ 6,	0,	NULL,			NULL		}, /* 73 */
-	{ 6,	0,	NULL,			NULL		}, /* 74 */
-	{ 6,	0,	NULL,			NULL		}, /* 75 */
-	{ 6,	0,	NULL,			NULL		}, /* 76 */
-	{ 6,	0,	NULL,			NULL		}, /* 77 */
-	{ 6,	0,	NULL,			NULL		}, /* 78 */
-	{ 6,	TF,	solaris_rmdir,		"rmdir"		}, /* 79 */
-	{ 6,	TF,	solaris_mkdir,		"mkdir"		}, /* 80 */
-	{ 6,	0,	solaris_getdents,	"getdents"	}, /* 81 */
-	{ 6,	0,	solaris_sginap,		"sginap"	}, /* 82 */
-	{ 6,	0,	solaris_sgikopt,	"sgikopt"	}, /* 83 */
-	{ 6,	0,	solaris_sysfs,		"sysfs"		}, /* 84 */
-	{ 6,	TN,	sys_getmsg,		"getmsg"	}, /* 85 */
-	{ 6,	TN,	sys_putmsg,		"putmsg"	}, /* 86 */
-	{ 6,	TN,	solaris_poll,		"poll"		}, /* 87 */
-	{ 6,	TF,	solaris_lstat,		"lstat"		}, /* 88 */
-	{ 6,	TF,	solaris_symlink,	"symlink"	}, /* 89 */
-	{ 6,	TF,	solaris_readlink,	"readlink"	}, /* 90 */
-	{ 6,	0,	solaris_setgroups,	"setgroups"	}, /* 91 */
-	{ 6,	0,	solaris_getgroups,	"getgroups"	}, /* 92 */
-	{ 6,	0,	solaris_fchmod,		"fchmod"	}, /* 93 */
-	{ 6,	0,	solaris_fchown,		"fchown"	}, /* 94 */
-	{ 6,	TS,	solaris_sigprocmask,	"sigprocmask"	}, /* 95 */
-	{ 6,	TS,	solaris_sigsuspend,	"sigsuspend"	}, /* 96 */
-	{ 6,	TS,	solaris_sigaltstack,	"sigaltstack"	}, /* 97 */
-	{ 6,	TS,	solaris_sigaction,	"sigaction"	}, /* 98 */
-	{ 6,	0,	solaris_spcall,		"spcall"	}, /* 99 */
-	{ 6,	0,	solaris_context,	"context"	}, /* 100 */
-	{ 6,	0,	solaris_evsys,		"evsys"		}, /* 101 */
-	{ 6,	0,	solaris_evtrapret,	"evtrapret"	}, /* 102 */
-	{ 6,	TF,	solaris_statvfs,	"statvfs"	}, /* 103 */
-	{ 6,	0,	solaris_fstatvfs,	"fstatvfs"	}, /* 104 */
-	{ 6,	0,	NULL,			NULL		}, /* 105 */
-	{ 6,	0,	solaris_nfssys,		"nfssys"	}, /* 106 */
-	{ 6,	TP,	solaris_waitid,		"waitid"	}, /* 107 */
-	{ 6,	0,	solaris_sigsendsys,	"sigsendsys"	}, /* 108 */
-	{ 6,	0,	solaris_hrtsys,		"hrtsys"	}, /* 109 */
-	{ 6,	0,	solaris_acancel,	"acancel"	}, /* 110 */
-	{ 6,	0,	solaris_async,		"async"		}, /* 111 */
-	{ 6,	0,	solaris_priocntlsys,	"priocntlsys"	}, /* 112 */
-	{ 6,	TF,	solaris_pathconf,	"pathconf"	}, /* 113 */
-	{ 6,	0,	solaris_mincore,	"mincore"	}, /* 114 */
-	{ 6,	TD|TM,	solaris_mmap,		"mmap"		}, /* 115 */
-	{ 6,	0,	solaris_mprotect,	"mprotect"	}, /* 116 */
-	{ 6,	0,	solaris_munmap,		"munmap"	}, /* 117 */
-	{ 6,	0,	solaris_fpathconf,	"fpathconf"	}, /* 118 */
-	{ 6,	TP,	solaris_vfork,		"vfork"		}, /* 119 */
-	{ 6,	0,	solaris_fchdir,		"fchdir"	}, /* 120 */
-	{ 6,	0,	solaris_readv,		"readv"		}, /* 121 */
-	{ 6,	0,	solaris_writev,		"writev"	}, /* 122 */
-	{ 6,	TF,	solaris_xstat,		"xstat"		}, /* 123 */
-	{ 6,	TF,	solaris_lxstat,		"lxstat"	}, /* 124 */
-	{ 6,	0,	solaris_fxstat,		"fxstat"	}, /* 125 */
-	{ 6,	TF,	solaris_xmknod,		"xmknod"	}, /* 126 */
-	{ 6,	0,	solaris_clocal,		"clocal"	}, /* 127 */
-	{ 6,	0,	solaris_setrlimit,	"setrlimit"	}, /* 128 */
-	{ 6,	0,	solaris_getrlimit,	"getrlimit"	}, /* 129 */
-	{ 6,	TF,	solaris_lchown,		"lchown"	}, /* 130 */
-	{ 6,	0,	solaris_memcntl,	"memcntl"	}, /* 131 */
-	{ 6,	TN,	solaris_getpmsg,	"getpmsg"	}, /* 132 */
-	{ 6,	TN,	solaris_putpmsg,	"putpmsg"	}, /* 133 */
-	{ 6,	TF,	solaris_rename,		"rename"	}, /* 134 */
-	{ 6,	0,	solaris_uname,		"uname"		}, /* 135 */
-	{ 6,	0,	solaris_setegid,	"setegid"	}, /* 136 */
-	{ 6,	0,	solaris_sysconfig,	"sysconfig"	}, /* 137 */
-	{ 6,	0,	solaris_adjtime,	"adjtime"	}, /* 138 */
-	{ 6,	0,	solaris_sysinfo,	"sysinfo"	}, /* 139 */
-	{ 6,	0,	NULL,			NULL		}, /* 140 */
-	{ 6,	0,	solaris_seteuid,	"seteuid"	}, /* 141 */
-	{ 6,	0,	solaris_vtrace,		"vtrace"	}, /* 142 */
-	{ 6,	TP,	solaris_fork1,		"fork1"		}, /* 143 */
-	{ 6,	TS,	solaris_sigtimedwait,	"sigtimedwait"	}, /* 144 */
-	{ 6,	0,	solaris_lwp_info,	"lwp_info"	}, /* 145 */
-	{ 6,	0,	solaris_yield,		"yield"		}, /* 146 */
-	{ 6,	0,	solaris_lwp_sema_wait,	"lwp_sema_wait"	}, /* 147 */
-	{ 6,	0,	solaris_lwp_sema_post,	"lwp_sema_post"	}, /* 148 */
-	{ 6,	0,	NULL,			NULL		}, /* 149 */
-	{ 6,	0,	NULL,			NULL		}, /* 150 */
-	{ 6,	0,	NULL,			NULL		}, /* 151 */
-	{ 6,	0,	solaris_modctl,		"modctl"	}, /* 152 */
-	{ 6,	0,	solaris_fchroot,	"fchroot"	}, /* 153 */
-	{ 6,	TF,	solaris_utimes,		"utimes"	}, /* 154 */
-	{ 6,	0,	solaris_vhangup,	"vhangup"	}, /* 155 */
-	{ 6,	0,	solaris_gettimeofday,	"gettimeofday"	}, /* 156 */
-	{ 6,	0,	solaris_getitimer,	"getitimer"	}, /* 157 */
-	{ 6,	0,	solaris_setitimer,	"setitimer"	}, /* 158 */
-	{ 6,	0,	solaris_lwp_create,	"lwp_create"	}, /* 159 */
-	{ 6,	0,	solaris_lwp_exit,	"lwp_exit"	}, /* 160 */
-	{ 6,	0,	solaris_lwp_suspend,	"lwp_suspend"	}, /* 161 */
-	{ 6,	0,	solaris_lwp_continue,	"lwp_continue"	}, /* 162 */
-	{ 6,	0,	solaris_lwp_kill,	"lwp_kill"	}, /* 163 */
-	{ 6,	0,	solaris_lwp_self,	"lwp_self"	}, /* 164 */
-	{ 6,	0,	solaris_lwp_setprivate,	"lwp_setprivate"}, /* 165 */
-	{ 6,	0,	solaris_lwp_getprivate,	"lwp_getprivate"}, /* 166 */
-	{ 6,	0,	solaris_lwp_wait,	"lwp_wait"	}, /* 167 */
-	{ 6,	0,	solaris_lwp_mutex_unlock,"lwp_mutex_unlock"}, /* 168 */
-	{ 6,	0,	solaris_lwp_mutex_lock,	"lwp_mutex_lock"}, /* 169 */
-	{ 6,	0,	solaris_lwp_cond_wait,	"lwp_cond_wait"}, /* 170 */
-	{ 6,	0,	solaris_lwp_cond_signal,"lwp_cond_signal"}, /* 171 */
-	{ 6,	0,	solaris_lwp_cond_broadcast,"lwp_cond_broadcast"}, /* 172 */
-	{ 6,	0,	solaris_pread,		"pread"		}, /* 173 */
-	{ 6,	0,	solaris_pwrite,		"pwrite"	}, /* 174 */
-	{ 6,	0,	solaris_llseek,		"llseek"	}, /* 175 */
-	{ 6,	0,	solaris_inst_sync,	"inst_sync"	}, /* 176 */
-	{ 6,	0,	NULL,			NULL		}, /* 177 */
-	{ 6,	0,	NULL,			NULL		}, /* 178 */
-	{ 6,	0,	NULL,			NULL		}, /* 179 */
-	{ 6,	0,	NULL,			NULL		}, /* 180 */
-	{ 6,	0,	NULL,			NULL		}, /* 181 */
-	{ 6,	0,	NULL,			NULL		}, /* 182 */
-	{ 6,	0,	NULL,			NULL		}, /* 183 */
-	{ 6,	0,	NULL,			NULL		}, /* 184 */
-	{ 6,	0,	NULL,			NULL		}, /* 185 */
-	{ 6,	0,	solaris_auditsys,	"auditsys"	}, /* 186 */
-	{ 6,	0,	solaris_processor_bind,	"processor_bind"}, /* 187 */
-	{ 6,	0,	solaris_processor_info,	"processor_info"}, /* 188 */
-	{ 6,	0,	solaris_p_online,	"p_online"	}, /* 189 */
-	{ 6,	0,	solaris_sigqueue,	"sigqueue"	}, /* 190 */
-	{ 6,	0,	solaris_clock_gettime,	"clock_gettime"	}, /* 191 */
-	{ 6,	0,	solaris_clock_settime,	"clock_settime"	}, /* 192 */
-	{ 6,	0,	solaris_clock_getres,	"clock_getres"	}, /* 193 */
-	{ 6,	0,	solaris_timer_create,	"timer_create"	}, /* 194 */
-	{ 6,	0,	solaris_timer_delete,	"timer_delete"	}, /* 195 */
-	{ 6,	0,	solaris_timer_settime,	"timer_settime"	}, /* 196 */
-	{ 6,	0,	solaris_timer_gettime,	"timer_gettime"	}, /* 197 */
-	{ 6,	0,	solaris_timer_getoverrun,"timer_getoverrun"}, /* 198 */
-	{ 6,	0,	solaris_nanosleep,	"nanosleep"	}, /* 199 */
-	{ 6,	0,	NULL,			NULL		}, /* 200 */
-	{ 6,	0,	NULL,			NULL		}, /* 201 */
-	{ 6,	0,	NULL,			NULL		}, /* 202 */
-	{ 6,	0,	NULL,			NULL		}, /* 203 */
-	{ 6,	0,	NULL,			NULL		}, /* 204 */
-	{ 6,	0,	NULL,			NULL		}, /* 205 */
-	{ 6,	0,	NULL,			NULL		}, /* 206 */
-	{ 6,	0,	NULL,			NULL		}, /* 207 */
-	{ 6,	0,	NULL,			NULL		}, /* 208 */
-	{ 6,	0,	NULL,			NULL		}, /* 209 */
-	{ 6,	0,	NULL,			NULL		}, /* 210 */
-	{ 6,	0,	NULL,			NULL		}, /* 211 */
-	{ 6,	0,	NULL,			NULL		}, /* 212 */
-	{ 6,	0,	NULL,			NULL		}, /* 213 */
-	{ 6,	0,	NULL,			NULL		}, /* 214 */
-	{ 6,	0,	NULL,			NULL		}, /* 215 */
-	{ 6,	0,	NULL,			NULL		}, /* 216 */
-	{ 6,	0,	NULL,			NULL		}, /* 217 */
-	{ 6,	0,	NULL,			NULL		}, /* 218 */
-	{ 6,	0,	NULL,			NULL		}, /* 219 */
-	{ 6,	0,	NULL,			NULL		}, /* 220 */
-	{ 6,	0,	NULL,			NULL		}, /* 221 */
-	{ 6,	0,	NULL,			NULL		}, /* 222 */
-	{ 6,	0,	NULL,			NULL		}, /* 223 */
-	{ 6,	0,	NULL,			NULL		}, /* 224 */
-	{ 6,	0,	NULL,			NULL		}, /* 225 */
-	{ 6,	0,	NULL,			NULL		}, /* 226 */
-	{ 6,	0,	NULL,			NULL		}, /* 227 */
-	{ 6,	0,	NULL,			NULL		}, /* 228 */
-	{ 6,	0,	NULL,			NULL		}, /* 229 */
-	{ 6,	0,	NULL,			NULL		}, /* 230 */
-	{ 6,	0,	NULL,			NULL		}, /* 231 */
-	{ 6,	0,	NULL,			NULL		}, /* 232 */
-	{ 6,	0,	NULL,			NULL		}, /* 233 */
-	{ 6,	0,	NULL,			NULL		}, /* 234 */
-	{ 6,	0,	NULL,			NULL		}, /* 235 */
-	{ 6,	0,	NULL,			NULL		}, /* 236 */
-	{ 6,	0,	NULL,			NULL		}, /* 237 */
-	{ 6,	0,	NULL,			NULL		}, /* 238 */
-	{ 6,	0,	NULL,			NULL		}, /* 239 */
-	{ 6,	0,	NULL,			NULL		}, /* 240 */
-	{ 6,	0,	NULL,			NULL		}, /* 241 */
-	{ 6,	0,	NULL,			NULL		}, /* 242 */
-	{ 6,	0,	NULL,			NULL		}, /* 243 */
-	{ 6,	0,	NULL,			NULL		}, /* 244 */
-	{ 6,	0,	NULL,			NULL		}, /* 245 */
-	{ 6,	0,	NULL,			NULL		}, /* 246 */
-	{ 6,	0,	NULL,			NULL		}, /* 247 */
-	{ 6,	0,	NULL,			NULL		}, /* 248 */
-	{ 6,	0,	NULL,			NULL		}, /* 249 */
-	{ 6,	0,	NULL,			NULL		}, /* 250 */
-	{ 6,	0,	NULL,			NULL		}, /* 251 */
-	{ 6,	0,	NULL,			NULL		}, /* 252 */
-	{ 6,	0,	NULL,			NULL		}, /* 253 */
-	{ 6,	0,	NULL,			NULL		}, /* 254 */
-	{ 6,	0,	NULL,			NULL		}, /* 255 */
-	{ 6,	0,	NULL,			NULL		}, /* 256 */
-	{ 6,	0,	NULL,			NULL		}, /* 257 */
-	{ 6,	0,	NULL,			NULL		}, /* 258 */
-	{ 6,	0,	NULL,			NULL		}, /* 259 */
-	{ 6,	0,	NULL,			NULL		}, /* 260 */
-	{ 6,	0,	NULL,			NULL		}, /* 261 */
-	{ 6,	0,	NULL,			NULL		}, /* 262 */
-	{ 6,	0,	NULL,			NULL		}, /* 263 */
-	{ 6,	0,	NULL,			NULL		}, /* 264 */
-	{ 6,	0,	NULL,			NULL		}, /* 265 */
-	{ 6,	0,	NULL,			NULL		}, /* 266 */
-	{ 6,	0,	NULL,			NULL		}, /* 267 */
-	{ 6,	0,	NULL,			NULL		}, /* 268 */
-	{ 6,	0,	NULL,			NULL		}, /* 269 */
-	{ 6,	0,	NULL,			NULL		}, /* 270 */
-	{ 6,	0,	NULL,			NULL		}, /* 271 */
-	{ 6,	0,	NULL,			NULL		}, /* 272 */
-	{ 6,	0,	NULL,			NULL		}, /* 273 */
-	{ 6,	0,	NULL,			NULL		}, /* 274 */
-	{ 6,	0,	NULL,			NULL		}, /* 275 */
-	{ 6,	0,	NULL,			NULL		}, /* 276 */
-	{ 6,	0,	NULL,			NULL		}, /* 277 */
-	{ 6,	0,	NULL,			NULL		}, /* 278 */
-	{ 6,	0,	NULL,			NULL		}, /* 279 */
-	{ 6,	0,	NULL,			NULL		}, /* 280 */
-	{ 6,	0,	NULL,			NULL		}, /* 281 */
-	{ 6,	0,	NULL,			NULL		}, /* 282 */
-	{ 6,	0,	NULL,			NULL		}, /* 283 */
-	{ 6,	0,	NULL,			NULL		}, /* 284 */
-	{ 6,	0,	NULL,			NULL		}, /* 285 */
-	{ 6,	0,	NULL,			NULL		}, /* 286 */
-	{ 6,	0,	NULL,			NULL		}, /* 287 */
-	{ 6,	0,	NULL,			NULL		}, /* 288 */
-	{ 6,	0,	NULL,			NULL		}, /* 289 */
-	{ 6,	0,	NULL,			NULL		}, /* 290 */
-	{ 6,	0,	NULL,			NULL		}, /* 291 */
-	{ 6,	0,	NULL,			NULL		}, /* 292 */
-	{ 6,	0,	NULL,			NULL		}, /* 293 */
-	{ 6,	0,	NULL,			NULL		}, /* 294 */
-	{ 6,	0,	NULL,			NULL		}, /* 295 */
-	{ 6,	0,	NULL,			NULL		}, /* 296 */
-	{ 6,	0,	NULL,			NULL		}, /* 297 */
-	{ 6,	0,	NULL,			NULL		}, /* 298 */
-	{ 6,	0,	NULL,			NULL		}, /* 299 */
-
-	{ 6,	0,	solaris_getpgrp,	"getpgrp"	}, /* 300 */
-	{ 6,	0,	solaris_setpgrp,	"setpgrp"	}, /* 301 */
-	{ 6,	0,	solaris_getsid,		"getsid"	}, /* 302 */
-	{ 6,	0,	solaris_setsid,		"setsid"	}, /* 303 */
-	{ 6,	0,	solaris_getpgid,	"getpgid"	}, /* 304 */
-	{ 6,	0,	solaris_setpgid,	"setpgid"	}, /* 305 */
-	{ 6,	0,	NULL,			NULL		}, /* 306 */
-	{ 6,	0,	NULL,			NULL		}, /* 307 */
-	{ 6,	0,	NULL,			NULL		}, /* 308 */
-	{ 6,	0,	NULL,			NULL		}, /* 309 */
-
-	{ 6,	TS,	solaris_signal,		"signal"	}, /* 310 */
-	{ 6,	TS,	solaris_sigset,		"sigset"	}, /* 311 */
-	{ 6,	TS,	solaris_sighold,	"sighold"	}, /* 312 */
-	{ 6,	TS,	solaris_sigrelse,	"sigrelse"	}, /* 313 */
-	{ 6,	TS,	solaris_sigignore,	"sigignore"	}, /* 314 */
-	{ 6,	TS,	solaris_sigpause,	"sigpause"	}, /* 315 */
-	{ 6,	0,	NULL,			NULL		}, /* 316 */
-	{ 6,	0,	NULL,			NULL		}, /* 317 */
-	{ 6,	0,	NULL,			NULL		}, /* 318 */
-	{ 6,	0,	NULL,			NULL		}, /* 319 */
-
-	{ 6,	TI,	solaris_msgget,		"msgget"	}, /* 320 */
-	{ 6,	TI,	solaris_msgctl,		"msgctl"	}, /* 321 */
-	{ 6,	TI,	solaris_msgrcv,		"msgrcv"	}, /* 322 */
-	{ 6,	TI,	solaris_msgsnd,		"msgsnd"	}, /* 323 */
-	{ 6,	0,	NULL,			NULL		}, /* 324 */
-	{ 6,	0,	NULL,			NULL		}, /* 325 */
-	{ 6,	0,	NULL,			NULL		}, /* 326 */
-	{ 6,	0,	NULL,			NULL		}, /* 327 */
-	{ 6,	0,	NULL,			NULL		}, /* 328 */
-	{ 6,	0,	NULL,			NULL		}, /* 329 */
-
-	{ 6,	TI|TM,	solaris_shmat,		"shmat"		}, /* 330 */
-	{ 6,	TI,	solaris_shmctl,		"shmctl"	}, /* 331 */
-	{ 6,	TI|TM,	solaris_shmdt,		"shmdt"		}, /* 332 */
-	{ 6,	TI,	solaris_shmget,		"shmget"	}, /* 333 */
-	{ 6,	0,	NULL,			NULL		}, /* 334 */
-	{ 6,	0,	NULL,			NULL		}, /* 335 */
-	{ 6,	0,	NULL,			NULL		}, /* 336 */
-	{ 6,	0,	NULL,			NULL		}, /* 337 */
-	{ 6,	0,	NULL,			NULL		}, /* 338 */
-	{ 6,	0,	NULL,			NULL		}, /* 339 */
-
-	{ 6,	TI,	solaris_semctl,		"semctl"	}, /* 340 */
-	{ 6,	TI,	solaris_semget,		"semget"	}, /* 341 */
-	{ 6,	TI,	solaris_semop,		"semop"		}, /* 342 */
-	{ 6,	0,	NULL,			NULL		}, /* 343 */
-	{ 6,	0,	NULL,			NULL		}, /* 344 */
-	{ 6,	0,	NULL,			NULL		}, /* 345 */
-	{ 6,	0,	NULL,			NULL		}, /* 346 */
-	{ 6,	0,	NULL,			NULL		}, /* 347 */
-	{ 6,	0,	NULL,			NULL		}, /* 348 */
-	{ 6,	0,	NULL,			NULL		}, /* 349 */
-
-	{ 6,	0,	solaris_olduname,	"olduname"	}, /* 350 */
-	{ 6,	0,	printargs,		"utssys1"	}, /* 351 */
-	{ 6,	0,	solaris_ustat,		"ustat"		}, /* 352 */
-	{ 6,	0,	solaris_fusers,		"fusers"	}, /* 353 */
-	{ 6,	0,	NULL,			NULL		}, /* 354 */
-	{ 6,	0,	NULL,			NULL		}, /* 355 */
-	{ 6,	0,	NULL,			NULL		}, /* 356 */
-	{ 6,	0,	NULL,			NULL		}, /* 357 */
-	{ 6,	0,	NULL,			NULL		}, /* 358 */
-	{ 6,	0,	NULL,			NULL		}, /* 359 */
-
-	{ 6,	0,	printargs,		"sysfs0"	}, /* 360 */
-	{ 6,	0,	solaris_sysfs1,		"sysfs1"	}, /* 361 */
-	{ 6,	0,	solaris_sysfs2,		"sysfs2"	}, /* 362 */
-	{ 6,	0,	solaris_sysfs3,		"sysfs3"	}, /* 363 */
-	{ 6,	0,	NULL,			NULL		}, /* 364 */
-	{ 6,	0,	NULL,			NULL		}, /* 365 */
-	{ 6,	0,	NULL,			NULL		}, /* 366 */
-	{ 6,	0,	NULL,			NULL		}, /* 367 */
-	{ 6,	0,	NULL,			NULL		}, /* 368 */
-	{ 6,	0,	NULL,			NULL		}, /* 369 */
-
-	{ 6,	0,	printargs,		"spcall0"	}, /* 370 */
-	{ 6,	TS,	solaris_sigpending,	"sigpending"	}, /* 371 */
-	{ 6,	TS,	solaris_sigfillset,	"sigfillset"	}, /* 372 */
-	{ 6,	0,	NULL,			NULL		}, /* 373 */
-	{ 6,	0,	NULL,			NULL		}, /* 374 */
-	{ 6,	0,	NULL,			NULL		}, /* 375 */
-	{ 6,	0,	NULL,			NULL		}, /* 376 */
-	{ 6,	0,	NULL,			NULL		}, /* 377 */
-	{ 6,	0,	NULL,			NULL		}, /* 378 */
-	{ 6,	0,	NULL,			NULL		}, /* 379 */
-
-	{ 6,	0,	solaris_getcontext,	"getcontext"	}, /* 380 */
-	{ 6,	0,	solaris_setcontext,	"setcontext"	}, /* 381 */
-	{ 6,	0,	NULL,			NULL		}, /* 382 */
-	{ 6,	0,	NULL,			NULL		}, /* 383 */
-	{ 6,	0,	NULL,			NULL		}, /* 384 */
-	{ 6,	0,	NULL,			NULL		}, /* 385 */
-	{ 6,	0,	NULL,			NULL		}, /* 386 */
-	{ 6,	0,	NULL,			NULL		}, /* 387 */
-	{ 6,	0,	NULL,			NULL		}, /* 388 */
-	{ 6,	0,	NULL,			NULL		}, /* 389 */
-
-	{ 6,	0,	NULL,			NULL		}, /* 390 */
-	{ 6,	0,	NULL,			NULL		}, /* 391 */
-	{ 6,	0,	NULL,			NULL		}, /* 392 */
-	{ 6,	0,	NULL,			NULL		}, /* 393 */
-	{ 6,	0,	NULL,			NULL		}, /* 394 */
-	{ 6,	0,	NULL,			NULL		}, /* 395 */
-	{ 6,	0,	NULL,			NULL		}, /* 396 */
-	{ 6,	0,	NULL,			NULL		}, /* 397 */
-	{ 6,	0,	NULL,			NULL		}, /* 398 */
-	{ 6,	0,	NULL,			NULL		}, /* 399 */
diff --git a/linux/sparc64/arch_getrval2.c b/linux/sparc64/arch_getrval2.c
new file mode 100644
index 0000000..81f1556
--- /dev/null
+++ b/linux/sparc64/arch_getrval2.c
@@ -0,0 +1 @@
+#include "sparc/arch_getrval2.c"
diff --git a/linux/sparc64/arch_regs.c b/linux/sparc64/arch_regs.c
new file mode 100644
index 0000000..db38d88
--- /dev/null
+++ b/linux/sparc64/arch_regs.c
@@ -0,0 +1 @@
+#include "sparc/arch_regs.c"
diff --git a/linux/sparc64/arch_sigreturn.c b/linux/sparc64/arch_sigreturn.c
new file mode 100644
index 0000000..aeec981
--- /dev/null
+++ b/linux/sparc64/arch_sigreturn.c
@@ -0,0 +1 @@
+#include "sparc/arch_sigreturn.c"
diff --git a/linux/sparc64/dummy2.h b/linux/sparc64/dummy2.h
deleted file mode 100644
index 783d4ee..0000000
--- a/linux/sparc64/dummy2.h
+++ /dev/null
@@ -1,276 +0,0 @@
-/*
- * Copyright (c) 1993, 1994, 1995 Rick Sladkey <jrs@world.std.com>
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- * 3. The name of the author may not be used to endorse or promote products
- *    derived from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-/* still unfinished */
-
-#define solaris_sysmp printargs
-#define solaris_sginap printargs
-#define solaris_sgikopt printargs
-#define solaris_sysmips printargs
-#define solaris_sigreturn printargs
-#define solaris_recvmsg printargs
-#define solaris_sendmsg printargs
-#define solaris_nfssvc printargs
-#define solaris_getfh printargs
-#define solaris_async_daemon printargs
-#define solaris_exportfs printargs
-#define solaris_BSD_getime printargs
-#define solaris_sproc printargs
-#define solaris_procblk printargs
-#define solaris_sprocsp printargs
-#define solaris_msync printargs
-#define solaris_madvise printargs
-#define solaris_pagelock printargs
-#define solaris_quotactl printargs
-#define solaris_cacheflush printargs
-#define solaris_cachectl printargs
-#define solaris_nuname printargs
-#define solaris_sigpoll printargs
-#define solaris_swapctl printargs
-#define solaris_sigstack printargs
-#define solaris_sigsendset printargs
-#define solaris_priocntl printargs
-#define solaris_ksigqueue printargs
-#define solaris_lwp_sema_wait printargs
-#define solaris_memcntl printargs
-#define solaris_syscall printargs
-#define solaris_clocal printargs
-#define solaris_syssun printargs
-#define solaris_sysi86 printargs
-#define solaris_sysmachine printargs
-#define solaris_plock printargs
-#define solaris_pathconf printargs
-#define solaris_sigtimedwait printargs
-#define solaris_ulimit printargs
-#define solaris_ptrace printargs
-#define solaris_stty printargs
-#define solaris_lwp_info printargs
-#define solaris_priocntlsys printargs
-#define solaris_hrtsys printargs
-#define solaris_xenix printargs
-#define solaris_statfs printargs
-#define solaris_fstatfs printargs
-#define solaris_statvfs printargs
-#define solaris_fstatvfs printargs
-#define solaris_fork1 printargs
-#define solaris_sigsendsys printargs
-#define solaris_gtty printargs
-#define solaris_vtrace printargs
-#define solaris_fpathconf printargs
-#define solaris_evsys printargs
-#define solaris_acct printargs
-#define solaris_exec printargs
-#define solaris_lwp_sema_post printargs
-#define solaris_nfssys printargs
-#define solaris_sigaltstack printargs
-#define solaris_uadmin printargs
-#define solaris_umount printargs
-#define solaris_modctl printargs
-#define solaris_acancel printargs
-#define solaris_async printargs
-#define solaris_evtrapret printargs
-#define solaris_lwp_create printargs
-#define solaris_lwp_exit printargs
-#define solaris_lwp_suspend printargs
-#define solaris_lwp_continue printargs
-#define solaris_lwp_kill printargs
-#define solaris_lwp_self printargs
-#define solaris_lwp_setprivate printargs
-#define solaris_lwp_getprivate printargs
-#define solaris_lwp_wait printargs
-#define solaris_lwp_mutex_unlock printargs
-#define solaris_lwp_mutex_lock printargs
-#define solaris_lwp_cond_wait printargs
-#define solaris_lwp_cond_signal printargs
-#define solaris_lwp_cond_broadcast printargs
-#define solaris_llseek printargs
-#define solaris_inst_sync printargs
-#define solaris_auditsys printargs
-#define solaris_processor_bind printargs
-#define solaris_processor_info printargs
-#define solaris_p_online printargs
-#define solaris_sigqueue printargs
-#define solaris_clock_gettime printargs
-#define solaris_clock_settime printargs
-#define solaris_clock_getres printargs
-#define solaris_nanosleep printargs
-#define solaris_timer_create printargs
-#define solaris_timer_delete printargs
-#define solaris_timer_settime printargs
-#define solaris_timer_gettime printargs
-#define solaris_timer_getoverrun printargs
-#define solaris_signal printargs
-#define solaris_sigset printargs
-#define solaris_sighold printargs
-#define solaris_sigrelse printargs
-#define solaris_sigignore printargs
-#define solaris_sigpause printargs
-#define solaris_msgctl printargs
-#define solaris_msgget printargs
-#define solaris_msgrcv printargs
-#define solaris_msgsnd printargs
-#define solaris_shmat printargs
-#define solaris_shmctl printargs
-#define solaris_shmdt printargs
-#define solaris_shmget printargs
-#define solaris_semctl printargs
-#define solaris_semget printargs
-#define solaris_semop printargs
-#define solaris_olduname printargs
-#define solaris_ustat printargs
-#define solaris_fusers printargs
-#define solaris_sysfs1 printargs
-#define solaris_sysfs2 printargs
-#define solaris_sysfs3 printargs
-
-/* like another call */
-#define solaris_lchown solaris_chown
-#define solaris_setuid solaris_close
-#define solaris_seteuid solaris_close
-#define solaris_setgid solaris_close
-#define solaris_setegid solaris_close
-#define solaris_vhangup solaris_close
-#define solaris_fdsync solaris_close
-#define solaris_sigfillset solaris_sigpending
-#define solaris_vfork solaris_fork
-#define solaris_ksigaction solaris_sigaction
-#define solaris_BSDgetpgrp solaris_getpgrp
-#define solaris_BSDsetpgrp solaris_setpgrp
-#define solaris_waitsys solaris_waitid
-
-/* printargs does the right thing */
-#define solaris_sync printargs
-#define solaris_profil printargs
-#define solaris_yield printargs
-#define solaris_pause printargs
-#define solaris_sethostid printargs
-
-/* subfunction entry points */
-#define solaris_pgrpsys printargs
-#define solaris_sigcall printargs
-#define solaris_msgsys printargs
-#define solaris_shmsys printargs
-#define solaris_semsys printargs
-#define solaris_utssys printargs
-#define solaris_sysfs printargs
-#define solaris_spcall printargs
-#define solaris_context printargs
-
-/* same as linux */
-#define solaris_exit sys_exit
-#define solaris_fork sys_fork
-#define solaris_read sys_read
-#define solaris_write sys_write
-#define solaris_close sys_close
-#define solaris_creat sys_creat
-#define solaris_link sys_link
-#define solaris_unlink sys_unlink
-#define solaris_chdir sys_chdir
-#define solaris_time sys_time
-#define solaris_chmod sys_chmod
-#define solaris_lseek sys_lseek
-#define solaris_stime sys_stime
-#define solaris_alarm sys_alarm
-#define solaris_utime sys_utime
-#define solaris_access sys_access
-#define solaris_nice sys_nice
-#define solaris_dup sys_dup
-#define solaris_pipe sys_pipe
-#define solaris_times sys_times
-#define solaris_execve sys_execve
-#define solaris_umask sys_umask
-#define solaris_chroot sys_chroot
-#define solaris_rmdir sys_rmdir
-#define solaris_mkdir sys_mkdir
-#define solaris_getdents sys_getdents
-#define solaris_poll sys_poll
-#define solaris_symlink sys_symlink
-#define solaris_readlink sys_readlink
-#define solaris_setgroups sys_setgroups
-#define solaris_getgroups sys_getgroups
-#define solaris_fchmod sys_fchmod
-#define solaris_fchown sys_fchown
-#define solaris_mprotect sys_mprotect
-#define solaris_munmap sys_munmap
-#define solaris_readv sys_readv
-#define solaris_writev sys_writev
-#define solaris_chown sys_chown
-#define solaris_rename sys_rename
-#define solaris_gettimeofday sys_gettimeofday
-#define solaris_getitimer sys_getitimer
-#define solaris_setitimer sys_setitimer
-#define solaris_brk sys_brk
-#define solaris_mmap sys_mmap
-#define solaris_getsid sys_getsid
-#define solaris_setsid sys_setsid
-#define solaris_getpgid sys_getpgid
-#define solaris_setpgid sys_setpgid
-#define solaris_getpgrp sys_getpgrp
-
-/* These are handled according to current_personality */
-#define solaris_xstat sys_xstat
-#define solaris_fxstat sys_fxstat
-#define solaris_lxstat sys_xstat
-#define solaris_xmknod sys_xmknod
-#define solaris_stat sys_stat
-#define solaris_fstat sys_fstat
-#define solaris_lstat sys_lstat
-#define solaris_pread sys_pread
-#define solaris_pwrite sys_pwrite
-#define solaris_ioctl sys_ioctl
-#define solaris_mknod sys_mknod
-
-/* To be done */
-#define solaris_mount printargs
-#define solaris_sysinfo printargs
-#define solaris_sysconfig printargs
-#define solaris_getpmsg printargs
-#define solaris_putpmsg printargs
-#define solaris_wait printargs
-#define solaris_waitid printargs
-#define solaris_sigsuspend printargs
-#define solaris_setpgrp printargs
-#define solaris_getcontext printargs
-#define solaris_setcontext printargs
-#define solaris_getpid printargs
-#define solaris_getuid printargs
-#define solaris_kill printargs
-#define solaris_getgid printargs
-#define solaris_fcntl printargs
-#define solaris_getmsg printargs
-#define solaris_putmsg printargs
-#define solaris_sigprocmask printargs
-#define solaris_sigaction printargs
-#define solaris_sigpending printargs
-#define solaris_mincore printargs
-#define solaris_fchdir printargs
-#define solaris_setrlimit printargs
-#define solaris_getrlimit printargs
-#define solaris_uname printargs
-#define solaris_adjtime printargs
-#define solaris_fchroot printargs
-#define solaris_utimes printargs
diff --git a/linux/sparc64/errnoent1.h b/linux/sparc64/errnoent1.h
index d194023..c0f7787 100644
--- a/linux/sparc64/errnoent1.h
+++ b/linux/sparc64/errnoent1.h
@@ -1 +1 @@
-#include "sparc/errnoent1.h"
+#include "errnoent.h"
diff --git a/linux/sparc64/errnoent2.h b/linux/sparc64/errnoent2.h
deleted file mode 100644
index c0f7787..0000000
--- a/linux/sparc64/errnoent2.h
+++ /dev/null
@@ -1 +0,0 @@
-#include "errnoent.h"
diff --git a/linux/sparc64/get_error.c b/linux/sparc64/get_error.c
new file mode 100644
index 0000000..ee3a7e5
--- /dev/null
+++ b/linux/sparc64/get_error.c
@@ -0,0 +1,6 @@
+if (check_errno && sparc_regs.tstate & 0x1100000000UL) {
+	tcp->u_rval = -1;
+	tcp->u_error = sparc_regs.u_regs[U_REG_O0];
+} else {
+	tcp->u_rval = sparc_regs.u_regs[U_REG_O0];
+}
diff --git a/linux/sparc64/get_scno.c b/linux/sparc64/get_scno.c
new file mode 100644
index 0000000..b92366e
--- /dev/null
+++ b/linux/sparc64/get_scno.c
@@ -0,0 +1,19 @@
+/* Retrieve the syscall trap instruction. */
+unsigned long trap;
+errno = 0;
+trap = ptrace(PTRACE_PEEKTEXT, tcp->pid, (char *)sparc_regs.tpc, 0);
+if (errno)
+	return -1;
+trap >>= 32;
+switch (trap) {
+case 0x91d02010:
+	/* Linux/SPARC syscall trap. */
+	update_personality(tcp, 0);
+	break;
+case 0x91d0206d:
+	/* Linux/SPARC64 syscall trap. */
+	update_personality(tcp, 1);
+	break;
+}
+
+scno = sparc_regs.u_regs[U_REG_G1];
diff --git a/linux/sparc64/get_syscall_args.c b/linux/sparc64/get_syscall_args.c
new file mode 100644
index 0000000..821c331
--- /dev/null
+++ b/linux/sparc64/get_syscall_args.c
@@ -0,0 +1 @@
+#include "sparc/get_syscall_args.c"
diff --git a/linux/sparc64/ioctlent1.h b/linux/sparc64/ioctlent1.h
deleted file mode 100644
index 8daf265..0000000
--- a/linux/sparc64/ioctlent1.h
+++ /dev/null
@@ -1 +0,0 @@
-#include "sparc/ioctlent1.h"
diff --git a/linux/sparc64/ioctls_arch2.h b/linux/sparc64/ioctls_arch1.h
similarity index 100%
rename from linux/sparc64/ioctls_arch2.h
rename to linux/sparc64/ioctls_arch1.h
diff --git a/linux/sparc64/ioctls_inc2.h b/linux/sparc64/ioctls_inc1.h
similarity index 100%
rename from linux/sparc64/ioctls_inc2.h
rename to linux/sparc64/ioctls_inc1.h
diff --git a/linux/sparc64/print_pc.c b/linux/sparc64/print_pc.c
new file mode 100644
index 0000000..11c0ac4
--- /dev/null
+++ b/linux/sparc64/print_pc.c
@@ -0,0 +1 @@
+tprintf(fmt, sparc_regs.tpc);
diff --git a/linux/sparc64/signalent1.h b/linux/sparc64/signalent1.h
index 9df023e..093cba7 100644
--- a/linux/sparc64/signalent1.h
+++ b/linux/sparc64/signalent1.h
@@ -1 +1 @@
-#include "sparc/signalent1.h"
+#include "signalent.h"
diff --git a/linux/sparc64/signalent2.h b/linux/sparc64/signalent2.h
deleted file mode 100644
index 093cba7..0000000
--- a/linux/sparc64/signalent2.h
+++ /dev/null
@@ -1 +0,0 @@
-#include "signalent.h"
diff --git a/linux/sparc64/syscall1.h b/linux/sparc64/syscall1.h
deleted file mode 100644
index 6f30b74..0000000
--- a/linux/sparc64/syscall1.h
+++ /dev/null
@@ -1,498 +0,0 @@
-/*
- * Copyright (c) 1993, 1994, 1995 Rick Sladkey <jrs@world.std.com>
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- * 3. The name of the author may not be used to endorse or promote products
- *    derived from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#define	SOLARIS_syscall	0
-#define	SOLARIS_exit	1
-#define	SOLARIS_fork	2
-#define	SOLARIS_read	3
-#define	SOLARIS_write	4
-#define	SOLARIS_open	5
-#define	SOLARIS_close	6
-#define	SOLARIS_wait	7
-#define	SOLARIS_creat	8
-#define	SOLARIS_link	9
-#define	SOLARIS_unlink	10
-#define	SOLARIS_exec	11
-#define	SOLARIS_chdir	12
-#define	SOLARIS_time	13
-#define	SOLARIS_mknod	14
-#define	SOLARIS_chmod	15
-#define	SOLARIS_chown	16
-#define	SOLARIS_brk		17
-#define	SOLARIS_stat	18
-#define	SOLARIS_lseek	19
-#define	SOLARIS_getpid	20
-#define	SOLARIS_mount	21
-#define	SOLARIS_umount	22
-#define	SOLARIS_setuid	23
-#define	SOLARIS_getuid	24
-#define	SOLARIS_stime	25
-#define	SOLARIS_ptrace	26
-#define	SOLARIS_alarm	27
-#define	SOLARIS_fstat	28
-#define	SOLARIS_pause	29
-#define	SOLARIS_utime	30
-#define	SOLARIS_stty	31
-#define	SOLARIS_gtty	32
-#define	SOLARIS_access	33
-#define	SOLARIS_nice	34
-#define	SOLARIS_statfs	35
-#define	SOLARIS_sync	36
-#define	SOLARIS_kill	37
-#define	SOLARIS_fstatfs	38
-#define	SOLARIS_pgrpsys	39
-#define	SOLARIS_xenix	40
-#define	SOLARIS_dup		41
-#define	SOLARIS_pipe	42
-#define	SOLARIS_times	43
-#define	SOLARIS_profil	44
-#define	SOLARIS_plock	45
-#define	SOLARIS_setgid	46
-#define	SOLARIS_getgid	47
-#define	SOLARIS_signal	48
-#define	SOLARIS_msgsys	49
-#define	SOLARIS_syssun	50
-#define	SOLARIS_acct	51
-#define	SOLARIS_shmsys	52
-#define	SOLARIS_semsys	53
-#define	SOLARIS_ioctl	54
-#define	SOLARIS_uadmin	55
-#define	SOLARIS_utssys	57
-#define	SOLARIS_fdsync	58
-#define	SOLARIS_execve	59
-#define	SOLARIS_umask	60
-#define	SOLARIS_chroot	61
-#define	SOLARIS_fcntl	62
-#define	SOLARIS_ulimit	63
-#define	SOLARIS_rmdir	79
-#define	SOLARIS_mkdir	80
-#define	SOLARIS_getdents	81
-#define	SOLARIS_sysfs	84
-#define	SOLARIS_getmsg	85
-#define	SOLARIS_putmsg	86
-#define	SOLARIS_poll	87
-#define	SOLARIS_lstat	88
-#define	SOLARIS_symlink	89
-#define	SOLARIS_readlink	90
-#define	SOLARIS_setgroups	91
-#define	SOLARIS_getgroups	92
-#define	SOLARIS_fchmod	93
-#define	SOLARIS_fchown	94
-#define	SOLARIS_sigprocmask	95
-#define	SOLARIS_sigsuspend	96
-#define	SOLARIS_sigaltstack	97
-#define	SOLARIS_sigaction	98
-#define	SOLARIS_sigpending	99
-#define	SOLARIS_context	100
-#define	SOLARIS_evsys	101
-#define	SOLARIS_evtrapret	102
-#define	SOLARIS_statvfs	103
-#define	SOLARIS_fstatvfs	104
-#define	SOLARIS_nfssys	106
-#define	SOLARIS_waitsys	107
-#define	SOLARIS_sigsendsys	108
-#define	SOLARIS_hrtsys	109
-#define	SOLARIS_acancel	110
-#define	SOLARIS_async	111
-#define	SOLARIS_priocntlsys	112
-#define	SOLARIS_pathconf	113
-#define	SOLARIS_mincore	114
-#define	SOLARIS_mmap	115
-#define	SOLARIS_mprotect	116
-#define	SOLARIS_munmap	117
-#define	SOLARIS_fpathconf	118
-#define	SOLARIS_vfork	119
-#define	SOLARIS_fchdir	120
-#define	SOLARIS_readv	121
-#define	SOLARIS_writev	122
-#define	SOLARIS_xstat	123
-#define	SOLARIS_lxstat	124
-#define	SOLARIS_fxstat	125
-#define	SOLARIS_xmknod	126
-#define	SOLARIS_clocal	127
-#define	SOLARIS_setrlimit	128
-#define	SOLARIS_getrlimit	129
-#define	SOLARIS_lchown	130
-#define	SOLARIS_memcntl	131
-#define	SOLARIS_getpmsg	132
-#define	SOLARIS_putpmsg	133
-#define	SOLARIS_rename	134
-#define	SOLARIS_uname	135
-#define	SOLARIS_setegid	136
-#define	SOLARIS_sysconfig	137
-#define	SOLARIS_adjtime	138
-#define	SOLARIS_systeminfo	139
-#define	SOLARIS_seteuid	141
-#define	SOLARIS_vtrace	142
-#define	SOLARIS_fork1	143
-#define	SOLARIS_sigtimedwait	144
-#define	SOLARIS_lwp_info	145
-#define	SOLARIS_yield	146
-#define	SOLARIS_lwp_sema_wait	147
-#define	SOLARIS_lwp_sema_post	148
-#define	SOLARIS_modctl	152
-#define	SOLARIS_fchroot	153
-#define	SOLARIS_utimes	154
-#define	SOLARIS_vhangup	155
-#define	SOLARIS_gettimeofday	156
-#define	SOLARIS_getitimer		157
-#define	SOLARIS_setitimer		158
-#define	SOLARIS_lwp_create		159
-#define	SOLARIS_lwp_exit		160
-#define	SOLARIS_lwp_suspend		161
-#define	SOLARIS_lwp_continue	162
-#define	SOLARIS_lwp_kill		163
-#define	SOLARIS_lwp_self		164
-#define	SOLARIS_lwp_setprivate	165
-#define	SOLARIS_lwp_getprivate	166
-#define	SOLARIS_lwp_wait		167
-#define	SOLARIS_lwp_mutex_unlock	168
-#define	SOLARIS_lwp_mutex_lock	169
-#define	SOLARIS_lwp_cond_wait	170
-#define	SOLARIS_lwp_cond_signal	171
-#define	SOLARIS_lwp_cond_broadcast	172
-#define	SOLARIS_pread		173
-#define	SOLARIS_pwrite		174
-#define	SOLARIS_llseek		175
-#define	SOLARIS_inst_sync		176
-#define	SOLARIS_kaio		178
-#define	SOLARIS_tsolsys		184
-#define	SOLARIS_acl			185
-#define	SOLARIS_auditsys		186
-#define	SOLARIS_processor_bind	187
-#define	SOLARIS_processor_info	188
-#define	SOLARIS_p_online		189
-#define	SOLARIS_sigqueue		190
-#define	SOLARIS_clock_gettime	191
-#define	SOLARIS_clock_settime	192
-#define	SOLARIS_clock_getres	193
-#define	SOLARIS_timer_create	194
-#define	SOLARIS_timer_delete	195
-#define	SOLARIS_timer_settime	196
-#define	SOLARIS_timer_gettime	197
-#define	SOLARIS_timer_getoverrun	198
-#define	SOLARIS_nanosleep		199
-#define	SOLARIS_facl		200
-#define	SOLARIS_door		201
-#define	SOLARIS_setreuid		202
-#define	SOLARIS_setregid		203
-#define	SOLARIS_signotifywait	210
-#define	SOLARIS_lwp_sigredirect	211
-#define	SOLARIS_lwp_alarm		212
-
-#include "dummy2.h"
-
-extern int solaris_syscall();
-extern int solaris_exit();
-extern int solaris_fork();
-extern int solaris_read();
-extern int solaris_write();
-extern int solaris_open();
-extern int solaris_close();
-extern int solaris_wait();
-extern int solaris_creat();
-extern int solaris_link();
-extern int solaris_unlink();
-extern int solaris_exec();
-extern int solaris_chdir();
-extern int solaris_time();
-extern int solaris_mknod();
-extern int solaris_chmod();
-extern int solaris_chown();
-extern int solaris_brk();
-extern int solaris_stat();
-extern int solaris_lseek();
-extern int solaris_getpid();
-extern int solaris_mount();
-extern int solaris_umount();
-extern int solaris_setuid();
-extern int solaris_getuid();
-extern int solaris_stime();
-extern int solaris_ptrace();
-extern int solaris_alarm();
-extern int solaris_fstat();
-extern int solaris_pause();
-extern int solaris_utime();
-extern int solaris_stty();
-extern int solaris_gtty();
-extern int solaris_access();
-extern int solaris_nice();
-extern int solaris_statfs();
-extern int solaris_sync();
-extern int solaris_kill();
-extern int solaris_fstatfs();
-extern int solaris_pgrpsys();
-extern int solaris_setpgrp();
-extern int solaris_xenix();
-extern int solaris_syssgi();
-extern int solaris_dup();
-extern int solaris_pipe();
-extern int solaris_times();
-extern int solaris_profil();
-extern int solaris_plock();
-extern int solaris_setgid();
-extern int solaris_getgid();
-extern int solaris_sigcall();
-extern int solaris_msgsys();
-extern int solaris_syssun();
-extern int solaris_sysi86();
-extern int solaris_sysmips();
-extern int solaris_sysmachine();
-extern int solaris_acct();
-extern int solaris_shmsys();
-extern int solaris_semsys();
-extern int solaris_ioctl();
-extern int solaris_uadmin();
-extern int solaris_utssys();
-extern int solaris_fdsync();
-extern int solaris_execve();
-extern int solaris_umask();
-extern int solaris_chroot();
-extern int solaris_fcntl();
-extern int solaris_ulimit();
-extern int solaris_rmdir();
-extern int solaris_mkdir();
-extern int solaris_getdents();
-extern int solaris_sysfs();
-extern int solaris_getmsg();
-extern int solaris_putmsg();
-extern int solaris_poll();
-extern int solaris_lstat();
-extern int solaris_symlink();
-extern int solaris_readlink();
-extern int solaris_setgroups();
-extern int solaris_getgroups();
-extern int solaris_fchmod();
-extern int solaris_fchown();
-extern int solaris_sigprocmask();
-extern int solaris_sigsuspend();
-extern int solaris_sigaltstack();
-extern int solaris_sigaction();
-extern int solaris_spcall();
-extern int solaris_context();
-extern int solaris_evsys();
-extern int solaris_evtrapret();
-extern int solaris_statvfs();
-extern int solaris_fstatvfs();
-extern int solaris_nfssys();
-extern int solaris_waitid();
-extern int solaris_sigsendsys();
-extern int solaris_hrtsys();
-extern int solaris_acancel();
-extern int solaris_async();
-extern int solaris_priocntlsys();
-extern int solaris_pathconf();
-extern int solaris_mincore();
-extern int solaris_mmap();
-extern int solaris_mprotect();
-extern int solaris_munmap();
-extern int solaris_fpathconf();
-extern int solaris_vfork();
-extern int solaris_fchdir();
-extern int solaris_readv();
-extern int solaris_writev();
-extern int solaris_xstat();
-extern int solaris_lxstat();
-extern int solaris_fxstat();
-extern int solaris_xmknod();
-extern int solaris_clocal();
-extern int solaris_setrlimit();
-extern int solaris_getrlimit();
-extern int solaris_lchown();
-extern int solaris_memcntl();
-extern int solaris_getpmsg();
-extern int solaris_putpmsg();
-extern int solaris_rename();
-extern int solaris_uname();
-extern int solaris_setegid();
-extern int solaris_sysconfig();
-extern int solaris_adjtime();
-extern int solaris_sysinfo();
-extern int solaris_seteuid();
-extern int solaris_vtrace();
-extern int solaris_fork1();
-extern int solaris_sigtimedwait();
-extern int solaris_lwp_info();
-extern int solaris_yield();
-extern int solaris_lwp_sema_wait();
-extern int solaris_lwp_sema_post();
-extern int solaris_modctl();
-extern int solaris_fchroot();
-extern int solaris_utimes();
-extern int solaris_vhangup();
-extern int solaris_gettimeofday();
-extern int solaris_getitimer();
-extern int solaris_setitimer();
-extern int solaris_lwp_create();
-extern int solaris_lwp_exit();
-extern int solaris_lwp_suspend();
-extern int solaris_lwp_continue();
-extern int solaris_lwp_kill();
-extern int solaris_lwp_self();
-extern int solaris_lwp_setprivate();
-extern int solaris_lwp_getprivate();
-extern int solaris_lwp_wait();
-extern int solaris_lwp_mutex_unlock();
-extern int solaris_lwp_mutex_lock();
-extern int solaris_lwp_cond_wait();
-extern int solaris_lwp_cond_signal();
-extern int solaris_lwp_cond_broadcast();
-extern int solaris_pread();
-extern int solaris_pwrite();
-extern int solaris_llseek();
-extern int solaris_inst_sync();
-extern int solaris_auditsys();
-extern int solaris_processor_bind();
-extern int solaris_processor_info();
-extern int solaris_p_online();
-extern int solaris_sigqueue();
-extern int solaris_clock_gettime();
-extern int solaris_clock_settime();
-extern int solaris_clock_getres();
-extern int solaris_timer_create();
-extern int solaris_timer_delete();
-extern int solaris_timer_settime();
-extern int solaris_timer_gettime();
-extern int solaris_timer_getoverrun();
-extern int solaris_nanosleep();
-
-/* solaris_pgrpsys subcalls */
-
-extern int solaris_getpgrp(), solaris_setpgrp(), solaris_getsid();
-extern int solaris_setsid(), solaris_getpgid(), solaris_setpgid();
-
-#define SOLARIS_pgrpsys_subcall	300
-#define SOLARIS_getpgrp		(SOLARIS_pgrpsys_subcall + 0)
-#define SOLARIS_setpgrp		(SOLARIS_pgrpsys_subcall + 1)
-#define SOLARIS_getsid		(SOLARIS_pgrpsys_subcall + 2)
-#define SOLARIS_setsid		(SOLARIS_pgrpsys_subcall + 3)
-#define SOLARIS_getpgid		(SOLARIS_pgrpsys_subcall + 4)
-#define SOLARIS_setpgid		(SOLARIS_pgrpsys_subcall + 5)
-
-#define SOLARIS_pgrpsys_nsubcalls	6
-
-/* solaris_sigcall subcalls */
-
-#undef SOLARIS_signal
-#define SOLARIS_sigcall		48
-
-extern int solaris_signal(), solaris_sigset(), solaris_sighold();
-extern int solaris_sigrelse(), solaris_sigignore(), solaris_sigpause();
-
-#define SOLARIS_sigcall_subcall	310
-#define SOLARIS_signal		(SOLARIS_sigcall_subcall + 0)
-#define SOLARIS_sigset		(SOLARIS_sigcall_subcall + 1)
-#define SOLARIS_sighold		(SOLARIS_sigcall_subcall + 2)
-#define SOLARIS_sigrelse		(SOLARIS_sigcall_subcall + 3)
-#define SOLARIS_sigignore		(SOLARIS_sigcall_subcall + 4)
-#define SOLARIS_sigpause		(SOLARIS_sigcall_subcall + 5)
-
-#define SOLARIS_sigcall_nsubcalls	6
-
-/* msgsys subcalls */
-
-extern int solaris_msgget(), solaris_msgctl(), solaris_msgrcv(), solaris_msgsnd();
-
-#define SOLARIS_msgsys_subcall	320
-#define SOLARIS_msgget		(SOLARIS_msgsys_subcall + 0)
-#define SOLARIS_msgctl		(SOLARIS_msgsys_subcall + 1)
-#define SOLARIS_msgrcv		(SOLARIS_msgsys_subcall + 2)
-#define SOLARIS_msgsnd		(SOLARIS_msgsys_subcall + 3)
-
-#define SOLARIS_msgsys_nsubcalls	4
-
-/* shmsys subcalls */
-
-extern int solaris_shmat(), solaris_shmctl(), solaris_shmdt(), solaris_shmget();
-
-#define SOLARIS_shmsys_subcall	330
-#define SOLARIS_shmat		(SOLARIS_shmsys_subcall + 0)
-#define SOLARIS_shmctl		(SOLARIS_shmsys_subcall + 1)
-#define SOLARIS_shmdt		(SOLARIS_shmsys_subcall + 2)
-#define SOLARIS_shmget		(SOLARIS_shmsys_subcall + 3)
-
-#define SOLARIS_shmsys_nsubcalls	4
-
-/* semsys subcalls */
-
-extern int solaris_semctl(), solaris_semget(), solaris_semop();
-
-#define SOLARIS_semsys_subcall	340
-#define SOLARIS_semctl		(SOLARIS_semsys_subcall + 0)
-#define SOLARIS_semget		(SOLARIS_semsys_subcall + 1)
-#define SOLARIS_semop		(SOLARIS_semsys_subcall + 2)
-
-#define SOLARIS_semsys_nsubcalls	3
-
-/* utssys subcalls */
-
-extern int solaris_olduname(), solaris_ustat(), solaris_fusers();
-
-#define SOLARIS_utssys_subcall	350
-
-#define SOLARIS_olduname		(SOLARIS_utssys_subcall + 0)
-				/* 1 is unused */
-#define SOLARIS_ustat		(SOLARIS_utssys_subcall + 2)
-#define SOLARIS_fusers		(SOLARIS_utssys_subcall + 3)
-
-#define SOLARIS_utssys_nsubcalls	4
-
-/* sysfs subcalls */
-
-extern int solaris_sysfs1(), solaris_sysfs2(), solaris_sysfs3();
-
-#define SOLARIS_sysfs_subcall	360
-				/* 0 is unused */
-#define SOLARIS_sysfs1		(SOLARIS_sysfs_subcall + 1)
-#define SOLARIS_sysfs2		(SOLARIS_sysfs_subcall + 2)
-#define SOLARIS_sysfs3		(SOLARIS_sysfs_subcall + 3)
-
-#define SOLARIS_sysfs_nsubcalls	4
-
-/* solaris_spcall subcalls */
-
-#undef SOLARIS_sigpending
-#define SOLARIS_spcall		99
-
-extern int solaris_sigpending(), solaris_sigfillset();
-
-#define SOLARIS_spcall_subcall	370
-				/* 0 is unused */
-#define SOLARIS_sigpending		(SOLARIS_spcall_subcall + 1)
-#define SOLARIS_sigfillset		(SOLARIS_spcall_subcall + 2)
-
-#define SOLARIS_spcall_nsubcalls	3
-
-/* solaris_context subcalls */
-
-extern int solaris_getcontext(), solaris_setcontext();
-
-#define SOLARIS_context_subcall	380
-#define SOLARIS_getcontext		(SOLARIS_context_subcall + 0)
-#define SOLARIS_setcontext		(SOLARIS_context_subcall + 1)
-
-#define SOLARIS_context_nsubcalls	2
diff --git a/linux/sparc64/syscallent1.h b/linux/sparc64/syscallent1.h
index 821d77c..5f73f3c 100644
--- a/linux/sparc64/syscallent1.h
+++ b/linux/sparc64/syscallent1.h
@@ -1 +1,3 @@
-#include "../sparc/syscallent1.h"
+#define sys_mmap_4koff sys_mmap_pgoff
+#include "../sparc/syscallent.h"
+#undef sys_mmap_4koff
diff --git a/linux/sparc64/syscallent2.h b/linux/sparc64/syscallent2.h
deleted file mode 100644
index 776b5f1..0000000
--- a/linux/sparc64/syscallent2.h
+++ /dev/null
@@ -1 +0,0 @@
-#include "../sparc/syscallent.h"
diff --git a/linux/syscall.h b/linux/syscall.h
index 45d261a..dbf2d20 100644
--- a/linux/syscall.h
+++ b/linux/syscall.h
@@ -348,7 +348,6 @@
 #endif
 
 #if defined SPARC || defined SPARC64
-#include "sparc/syscall1.h"
 int sys_execv();
 int sys_getmsg();
 int sys_putmsg();
diff --git a/linux/tile/arch_regs.c b/linux/tile/arch_regs.c
new file mode 100644
index 0000000..455077c
--- /dev/null
+++ b/linux/tile/arch_regs.c
@@ -0,0 +1,2 @@
+struct pt_regs tile_regs; /* not static */
+#define ARCH_REGS_FOR_GETREGS tile_regs
diff --git a/linux/tile/arch_sigreturn.c b/linux/tile/arch_sigreturn.c
new file mode 100644
index 0000000..99e2bf8
--- /dev/null
+++ b/linux/tile/arch_sigreturn.c
@@ -0,0 +1,8 @@
+/* offset of ucontext in the kernel's sigframe structure */
+# define SIGFRAME_UC_OFFSET C_ABI_SAVE_AREA_SIZE + sizeof(siginfo_t)
+const long addr = tile_regs.sp + SIGFRAME_UC_OFFSET +
+		  offsetof(struct ucontext, uc_sigmask);
+
+tprints("{mask=");
+print_sigset_addr_len(tcp, addr, NSIG / 8);
+tprints("}");
diff --git a/linux/tile/get_error.c b/linux/tile/get_error.c
new file mode 100644
index 0000000..8b73dfa
--- /dev/null
+++ b/linux/tile/get_error.c
@@ -0,0 +1,12 @@
+/*
+ * The standard tile calling convention returns the value (or negative
+ * errno) in r0, and zero (or positive errno) in r1.
+ * Until at least kernel 3.8, however, the r1 value is not reflected
+ * in ptregs at this point, so we use r0 here.
+ */
+if (check_errno && is_negated_errno(tile_regs.regs[0])) {
+	tcp->u_rval = -1;
+	tcp->u_error = -tile_regs.regs[0];
+} else {
+	tcp->u_rval = tile_regs.regs[0];
+}
diff --git a/linux/tile/get_scno.c b/linux/tile/get_scno.c
new file mode 100644
index 0000000..1ae65c9
--- /dev/null
+++ b/linux/tile/get_scno.c
@@ -0,0 +1,17 @@
+unsigned int currpers;
+
+scno = tile_regs.regs[10];
+
+#ifdef __tilepro__
+currpers = 1;
+#else
+# ifndef PT_FLAGS_COMPAT
+#  define PT_FLAGS_COMPAT 0x10000  /* from Linux 3.8 on */
+# endif
+if (tile_regs.flags & PT_FLAGS_COMPAT)
+	currpers = 1;
+else
+	currpers = 0;
+#endif
+
+update_personality(tcp, currpers);
diff --git a/linux/tile/get_syscall_args.c b/linux/tile/get_syscall_args.c
new file mode 100644
index 0000000..33371d5
--- /dev/null
+++ b/linux/tile/get_syscall_args.c
@@ -0,0 +1,6 @@
+tcp->u_arg[0] = tile_regs.regs[0];
+tcp->u_arg[1] = tile_regs.regs[1];
+tcp->u_arg[2] = tile_regs.regs[2];
+tcp->u_arg[3] = tile_regs.regs[3];
+tcp->u_arg[4] = tile_regs.regs[4];
+tcp->u_arg[5] = tile_regs.regs[5];
diff --git a/linux/tile/print_pc.c b/linux/tile/print_pc.c
new file mode 100644
index 0000000..8a6894f
--- /dev/null
+++ b/linux/tile/print_pc.c
@@ -0,0 +1 @@
+tprintf(fmt, (unsigned long) tile_regs.pc);
diff --git a/linux/ubi-user.h b/linux/ubi-user.h
index a12c884..e9e56b3 100644
--- a/linux/ubi-user.h
+++ b/linux/ubi-user.h
@@ -307,7 +307,7 @@
 	__s16 name_len;
 	__s8 padding2[4];
 	char name[UBI_MAX_VOLUME_NAME + 1];
-} __attribute__((packed));
+} ATTRIBUTE_PACKED;
 
 /**
  * struct ubi_rsvol_req - a data structure used in volume re-size requests.
@@ -323,7 +323,7 @@
 struct ubi_rsvol_req {
 	__s64 bytes;
 	__s32 vol_id;
-} __attribute__((packed));
+} ATTRIBUTE_PACKED;
 
 /**
  * struct ubi_rnvol_req - volumes re-name request.
@@ -365,7 +365,7 @@
 		__s8  padding2[2];
 		char    name[UBI_MAX_VOLUME_NAME + 1];
 	} ents[UBI_MAX_RNVOL];
-} __attribute__((packed));
+} ATTRIBUTE_PACKED;
 
 /**
  * struct ubi_leb_change_req - a data structure used in atomic LEB change
@@ -389,7 +389,7 @@
 	__s32 bytes;
 	__s8  dtype; /* obsolete, do not use! */
 	__s8  padding[7];
-} __attribute__((packed));
+} ATTRIBUTE_PACKED;
 
 /**
  * struct ubi_map_req - a data structure used in map LEB requests.
@@ -401,7 +401,7 @@
 	__s32 lnum;
 	__s8  dtype; /* obsolete, do not use! */
 	__s8  padding[3];
-} __attribute__((packed));
+} ATTRIBUTE_PACKED;
 
 
 /**
@@ -415,6 +415,6 @@
 	__u8  property;
 	__u8  padding[7];
 	__u64 value;
-}  __attribute__((packed));
+}  ATTRIBUTE_PACKED;
 
 #endif /* __UBI_USER_H__ */
diff --git a/linux/x32/arch_regs.c b/linux/x32/arch_regs.c
new file mode 100644
index 0000000..62c70be
--- /dev/null
+++ b/linux/x32/arch_regs.c
@@ -0,0 +1 @@
+#include "x86_64/arch_regs.c"
diff --git a/linux/x32/arch_sigreturn.c b/linux/x32/arch_sigreturn.c
new file mode 100644
index 0000000..9a778fc
--- /dev/null
+++ b/linux/x32/arch_sigreturn.c
@@ -0,0 +1 @@
+#include "x86_64/arch_sigreturn.c"
diff --git a/linux/x32/get_error.c b/linux/x32/get_error.c
new file mode 100644
index 0000000..6c6fbaf
--- /dev/null
+++ b/linux/x32/get_error.c
@@ -0,0 +1 @@
+#include "x86_64/get_error.c"
diff --git a/linux/x32/get_scno.c b/linux/x32/get_scno.c
new file mode 100644
index 0000000..492863f
--- /dev/null
+++ b/linux/x32/get_scno.c
@@ -0,0 +1 @@
+#include "x86_64/get_scno.c"
diff --git a/linux/x32/get_syscall_args.c b/linux/x32/get_syscall_args.c
new file mode 100644
index 0000000..6cdb465
--- /dev/null
+++ b/linux/x32/get_syscall_args.c
@@ -0,0 +1 @@
+#include "x86_64/get_syscall_args.c"
diff --git a/linux/x32/print_pc.c b/linux/x32/print_pc.c
new file mode 100644
index 0000000..13ccdc2
--- /dev/null
+++ b/linux/x32/print_pc.c
@@ -0,0 +1 @@
+#include "x86_64/print_pc.c"
diff --git a/linux/x86_64/arch_regs.c b/linux/x86_64/arch_regs.c
new file mode 100644
index 0000000..1925dad
--- /dev/null
+++ b/linux/x86_64/arch_regs.c
@@ -0,0 +1,40 @@
+/*
+ * On i386, pt_regs and user_regs_struct are the same,
+ * but on 64 bit x86, user_regs_struct has six more fields:
+ * fs_base, gs_base, ds, es, fs, gs.
+ * PTRACE_GETREGS fills them too, so struct pt_regs would overflow.
+ */
+struct i386_user_regs_struct {
+	uint32_t ebx;
+	uint32_t ecx;
+	uint32_t edx;
+	uint32_t esi;
+	uint32_t edi;
+	uint32_t ebp;
+	uint32_t eax;
+	uint32_t xds;
+	uint32_t xes;
+	uint32_t xfs;
+	uint32_t xgs;
+	uint32_t orig_eax;
+	uint32_t eip;
+	uint32_t xcs;
+	uint32_t eflags;
+	uint32_t esp;
+	uint32_t xss;
+};
+static union {
+	struct user_regs_struct      x86_64_r;
+	struct i386_user_regs_struct i386_r;
+} x86_regs_union;
+#define x86_64_regs x86_regs_union.x86_64_r
+#define i386_regs   x86_regs_union.i386_r
+
+uint32_t *const i386_esp_ptr = &i386_regs.esp;
+uint64_t *const x86_64_rsp_ptr = (uint64_t *) &x86_64_regs.rsp;
+static struct iovec x86_io = {
+	.iov_base = &x86_regs_union
+};
+
+#define ARCH_REGS_FOR_GETREGSET x86_regs_union
+#define ARCH_IOVEC_FOR_GETREGSET x86_io
diff --git a/linux/x86_64/arch_sigreturn.c b/linux/x86_64/arch_sigreturn.c
new file mode 100644
index 0000000..62aeca5
--- /dev/null
+++ b/linux/x86_64/arch_sigreturn.c
@@ -0,0 +1,10 @@
+if (current_personality != 1) {
+	const unsigned long addr =
+		(unsigned long) *x86_64_rsp_ptr +
+		offsetof(struct ucontext, uc_sigmask);
+	tprints("{mask=");
+	print_sigset_addr_len(tcp, addr, NSIG / 8);
+	tprints("}");
+	return 0;
+}
+#include "i386/arch_sigreturn.c"
diff --git a/linux/x86_64/get_error.c b/linux/x86_64/get_error.c
new file mode 100644
index 0000000..29b7816
--- /dev/null
+++ b/linux/x86_64/get_error.c
@@ -0,0 +1,23 @@
+/*
+ * In X32, return value is 64-bit (llseek uses one).
+ * Using merely "long rax" would not work.
+ */
+long long rax;
+
+if (x86_io.iov_len == sizeof(i386_regs)) {
+	/* Sign extend from 32 bits */
+	rax = (int32_t) i386_regs.eax;
+} else {
+	rax = x86_64_regs.rax;
+}
+
+if (check_errno && is_negated_errno(rax)) {
+	tcp->u_rval = -1;
+	tcp->u_error = -rax;
+} else {
+	tcp->u_rval = rax;
+# ifdef X32
+	/* tcp->u_rval contains a truncated value */
+	tcp->u_lrval = rax;
+# endif
+}
diff --git a/linux/x86_64/get_scno.c b/linux/x86_64/get_scno.c
new file mode 100644
index 0000000..2eb0d5d
--- /dev/null
+++ b/linux/x86_64/get_scno.c
@@ -0,0 +1,107 @@
+#ifndef __X32_SYSCALL_BIT
+# define __X32_SYSCALL_BIT	0x40000000
+#endif
+
+unsigned int currpers;
+
+#if 1
+/* GETREGSET of NT_PRSTATUS tells us regset size,
+ * which unambiguously detects i386.
+ *
+ * Linux kernel distinguishes x86-64 and x32 processes
+ * solely by looking at __X32_SYSCALL_BIT:
+ * arch/x86/include/asm/compat.h::is_x32_task():
+ * if (task_pt_regs(current)->orig_ax & __X32_SYSCALL_BIT)
+ *         return true;
+ */
+if (x86_io.iov_len == sizeof(i386_regs)) {
+	scno = i386_regs.orig_eax;
+	currpers = 1;
+} else {
+	scno = x86_64_regs.orig_rax;
+	currpers = 0;
+	if (scno & __X32_SYSCALL_BIT) {
+		/*
+		 * Syscall number -1 requires special treatment:
+		 * it might be a side effect of SECCOMP_RET_ERRNO
+		 * filtering that sets orig_rax to -1
+		 * in some versions of linux kernel.
+		 * If that is the case, then
+		 * __X32_SYSCALL_BIT logic does not apply.
+		 */
+		if ((long long) x86_64_regs.orig_rax != -1) {
+			scno -= __X32_SYSCALL_BIT;
+			currpers = 2;
+		} else {
+# ifdef X32
+			currpers = 2;
+# endif
+		}
+	}
+}
+
+#elif 0
+/* cs = 0x33 for long mode (native 64 bit and x32)
+ * cs = 0x23 for compatibility mode (32 bit)
+ * ds = 0x2b for x32 mode (x86-64 in 32 bit)
+ */
+scno = x86_64_regs.orig_rax;
+switch (x86_64_regs.cs) {
+	case 0x23: currpers = 1; break;
+	case 0x33:
+		if (x86_64_regs.ds == 0x2b) {
+			currpers = 2;
+			scno &= ~__X32_SYSCALL_BIT;
+		} else
+			currpers = 0;
+		break;
+	default:
+		fprintf(stderr, "Unknown value CS=0x%08X while "
+			 "detecting personality of process "
+			 "PID=%d\n", (int)x86_64_regs.cs, tcp->pid);
+		currpers = current_personality;
+		break;
+}
+#elif 0
+/* This version analyzes the opcode of a syscall instruction.
+ * (int 0x80 on i386 vs. syscall on x86-64)
+ * It works, but is too complicated, and strictly speaking, unreliable.
+ */
+unsigned long call, rip = x86_64_regs.rip;
+/* sizeof(syscall) == sizeof(int 0x80) == 2 */
+rip -= 2;
+errno = 0;
+call = ptrace(PTRACE_PEEKTEXT, tcp->pid, (char *)rip, (char *)0);
+if (errno)
+	fprintf(stderr, "ptrace_peektext failed: %s\n",
+			strerror(errno));
+switch (call & 0xffff) {
+	/* x86-64: syscall = 0x0f 0x05 */
+	case 0x050f: currpers = 0; break;
+	/* i386: int 0x80 = 0xcd 0x80 */
+	case 0x80cd: currpers = 1; break;
+	default:
+		currpers = current_personality;
+		fprintf(stderr,
+			"Unknown syscall opcode (0x%04X) while "
+			"detecting personality of process "
+			"PID=%d\n", (int)call, tcp->pid);
+		break;
+}
+#endif
+
+#ifdef X32
+/* If we are built for a x32 system, then personality 0 is x32
+ * (not x86_64), and stracing of x86_64 apps is not supported.
+ * Stracing of i386 apps is still supported.
+ */
+if (currpers == 0) {
+	fprintf(stderr, "syscall_%lu(...) in unsupported "
+			"64-bit mode of process PID=%d\n",
+		scno, tcp->pid);
+	return 0;
+}
+currpers &= ~2; /* map 2,1 to 0,1 */
+#endif /* X32 */
+
+update_personality(tcp, currpers);
diff --git a/linux/x86_64/get_syscall_args.c b/linux/x86_64/get_syscall_args.c
new file mode 100644
index 0000000..0ccecdf
--- /dev/null
+++ b/linux/x86_64/get_syscall_args.c
@@ -0,0 +1,29 @@
+if (x86_io.iov_len != sizeof(i386_regs)) {
+	/* x86-64 or x32 ABI */
+	tcp->u_arg[0] = x86_64_regs.rdi;
+	tcp->u_arg[1] = x86_64_regs.rsi;
+	tcp->u_arg[2] = x86_64_regs.rdx;
+	tcp->u_arg[3] = x86_64_regs.r10;
+	tcp->u_arg[4] = x86_64_regs.r8;
+	tcp->u_arg[5] = x86_64_regs.r9;
+#ifdef X32
+	tcp->ext_arg[0] = x86_64_regs.rdi;
+	tcp->ext_arg[1] = x86_64_regs.rsi;
+	tcp->ext_arg[2] = x86_64_regs.rdx;
+	tcp->ext_arg[3] = x86_64_regs.r10;
+	tcp->ext_arg[4] = x86_64_regs.r8;
+	tcp->ext_arg[5] = x86_64_regs.r9;
+#endif
+} else {
+	/* i386 ABI */
+	/* Zero-extend from 32 bits */
+	/* Use widen_to_long(tcp->u_arg[N]) in syscall handlers
+	 * if you need to use *sign-extended* parameter.
+	 */
+	tcp->u_arg[0] = (long)(uint32_t)i386_regs.ebx;
+	tcp->u_arg[1] = (long)(uint32_t)i386_regs.ecx;
+	tcp->u_arg[2] = (long)(uint32_t)i386_regs.edx;
+	tcp->u_arg[3] = (long)(uint32_t)i386_regs.esi;
+	tcp->u_arg[4] = (long)(uint32_t)i386_regs.edi;
+	tcp->u_arg[5] = (long)(uint32_t)i386_regs.ebp;
+}
diff --git a/linux/x86_64/getregs_old.c b/linux/x86_64/getregs_old.c
new file mode 100644
index 0000000..6911eee
--- /dev/null
+++ b/linux/x86_64/getregs_old.c
@@ -0,0 +1,39 @@
+/*
+ * PTRACE_GETREGSET was added to the kernel in v2.6.25,
+ * a PTRACE_GETREGS based fallback is provided for old kernels.
+ */
+static void
+getregs_old(pid_t pid)
+{
+	/* Use old method, with unreliable heuristical detection of 32-bitness. */
+	get_regs_error = ptrace(PTRACE_GETREGS, pid, NULL, &x86_64_regs);
+	if (get_regs_error)
+		return;
+
+	if (x86_64_regs.cs == 0x23) {
+		x86_io.iov_len = sizeof(i386_regs);
+		/*
+		 * The order is important: i386_regs and x86_64_regs
+		 * are overlaid in memory!
+		 */
+		i386_regs.ebx = x86_64_regs.rbx;
+		i386_regs.ecx = x86_64_regs.rcx;
+		i386_regs.edx = x86_64_regs.rdx;
+		i386_regs.esi = x86_64_regs.rsi;
+		i386_regs.edi = x86_64_regs.rdi;
+		i386_regs.ebp = x86_64_regs.rbp;
+		i386_regs.eax = x86_64_regs.rax;
+		/* i386_regs.xds = x86_64_regs.ds; unused by strace */
+		/* i386_regs.xes = x86_64_regs.es; ditto... */
+		/* i386_regs.xfs = x86_64_regs.fs; */
+		/* i386_regs.xgs = x86_64_regs.gs; */
+		i386_regs.orig_eax = x86_64_regs.orig_rax;
+		i386_regs.eip = x86_64_regs.rip;
+		/* i386_regs.xcs = x86_64_regs.cs; */
+		/* i386_regs.eflags = x86_64_regs.eflags; */
+		i386_regs.esp = x86_64_regs.rsp;
+		/* i386_regs.xss = x86_64_regs.ss; */
+	} else {
+		x86_io.iov_len = sizeof(x86_64_regs);
+	}
+}
diff --git a/linux/x86_64/print_pc.c b/linux/x86_64/print_pc.c
new file mode 100644
index 0000000..71b080a
--- /dev/null
+++ b/linux/x86_64/print_pc.c
@@ -0,0 +1,4 @@
+if (x86_io.iov_len == sizeof(i386_regs))
+	tprintf(fmt, (unsigned long) i386_regs.eip);
+else
+	tprintf(fmt, (unsigned long) x86_64_regs.rip);
diff --git a/linux/xtensa/arch_regs.c b/linux/xtensa/arch_regs.c
new file mode 100644
index 0000000..1114cab
--- /dev/null
+++ b/linux/xtensa/arch_regs.c
@@ -0,0 +1 @@
+static long xtensa_a2;
diff --git a/linux/xtensa/get_error.c b/linux/xtensa/get_error.c
new file mode 100644
index 0000000..6efbb6e
--- /dev/null
+++ b/linux/xtensa/get_error.c
@@ -0,0 +1,6 @@
+if (check_errno && is_negated_errno(xtensa_a2)) {
+	tcp->u_rval = -1;
+	tcp->u_error = -xtensa_a2;
+} else {
+	tcp->u_rval = xtensa_a2;
+}
diff --git a/linux/xtensa/get_scno.c b/linux/xtensa/get_scno.c
new file mode 100644
index 0000000..4299163
--- /dev/null
+++ b/linux/xtensa/get_scno.c
@@ -0,0 +1,2 @@
+if (upeek(tcp->pid, SYSCALL_NR, &scno) < 0)
+	return -1;
diff --git a/linux/xtensa/get_syscall_args.c b/linux/xtensa/get_syscall_args.c
new file mode 100644
index 0000000..dca8788
--- /dev/null
+++ b/linux/xtensa/get_syscall_args.c
@@ -0,0 +1,7 @@
+/* arg0: a6, arg1: a3, arg2: a4, arg3: a5, arg4: a8, arg5: a9 */
+static const int xtensaregs[MAX_ARGS] = { 6, 3, 4, 5, 8, 9 };
+unsigned int i;
+
+for (i = 0; i < tcp->s_ent->nargs; ++i)
+	if (upeek(tcp->pid, REG_A_BASE + xtensaregs[i], &tcp->u_arg[i]) < 0)
+		return -1;
diff --git a/linux/xtensa/get_syscall_result.c b/linux/xtensa/get_syscall_result.c
new file mode 100644
index 0000000..0d2e697
--- /dev/null
+++ b/linux/xtensa/get_syscall_result.c
@@ -0,0 +1,2 @@
+if (upeek(tcp->pid, REG_A_BASE + 2, &xtensa_a2) < 0)
+	return -1;
diff --git a/linux/xtensa/print_pc.c b/linux/xtensa/print_pc.c
new file mode 100644
index 0000000..c0232e5
--- /dev/null
+++ b/linux/xtensa/print_pc.c
@@ -0,0 +1,6 @@
+long pc;
+if (upeek(tcp->pid, REG_PC, &pc) < 0) {
+	PRINTBADPC;
+	return;
+}
+tprintf(fmt, pc);
diff --git a/mem.c b/mem.c
index 5e1822f..4082658 100644
--- a/mem.c
+++ b/mem.c
@@ -34,8 +34,8 @@
 #include <asm/mman.h>
 #include <sys/mman.h>
 
-static unsigned long
-get_pagesize()
+unsigned long
+get_pagesize(void)
 {
 	static unsigned long pagesize;
 
@@ -106,7 +106,7 @@
 	 */
 	int i;
 	unsigned narrow_arg[6];
-	if (umoven(tcp, tcp->u_arg[0], sizeof(narrow_arg), (char *) narrow_arg) == -1)
+	if (umoven(tcp, tcp->u_arg[0], sizeof(narrow_arg), narrow_arg) == -1)
 		return 0;
 	for (i = 0; i < 6; i++)
 		u_arg[i] = (unsigned long) narrow_arg[i];
@@ -114,12 +114,12 @@
 	/* We are here only in personality 1 (i386) */
 	int i;
 	unsigned narrow_arg[6];
-	if (umoven(tcp, tcp->u_arg[0], sizeof(narrow_arg), (char *) narrow_arg) == -1)
+	if (umoven(tcp, tcp->u_arg[0], sizeof(narrow_arg), narrow_arg) == -1)
 		return 0;
 	for (i = 0; i < 6; ++i)
 		u_arg[i] = (unsigned long) narrow_arg[i];
 #else
-	if (umoven(tcp, tcp->u_arg[0], sizeof(u_arg), (char *) u_arg) == -1)
+	if (umoven(tcp, tcp->u_arg[0], sizeof(u_arg), u_arg) == -1)
 		return 0;
 #endif
 	return print_mmap(tcp, u_arg, (unsigned long) u_arg[5]);
@@ -134,7 +134,7 @@
 	int i;
 	unsigned narrow_arg[6];
 	unsigned long long offset;
-	if (umoven(tcp, tcp->u_arg[0], sizeof(narrow_arg), (char *) narrow_arg) == -1)
+	if (umoven(tcp, tcp->u_arg[0], sizeof(narrow_arg), narrow_arg) == -1)
 		return 0;
 	for (i = 0; i < 5; i++)
 		u_arg[i] = (unsigned long) narrow_arg[i];
@@ -362,7 +362,7 @@
 				tprints("...");
 				break;
 			}
-			if (umoven(tcp, cur, sizeof(n), (char *) &n) < 0) {
+			if (umoven(tcp, cur, sizeof(n), &n) < 0) {
 				tprints("?");
 				failed = 1;
 				break;
diff --git a/mknod.c b/mknod.c
index 07e9a45..1463232 100644
--- a/mknod.c
+++ b/mknod.c
@@ -1,6 +1,7 @@
 #include "defs.h"
 
 #include <fcntl.h>
+#include <sys/stat.h>
 
 #ifdef MAJOR_IN_SYSMACROS
 # include <sys/sysmacros.h>
diff --git a/net.c b/net.c
index cb29faa..58c54c8 100644
--- a/net.c
+++ b/net.c
@@ -1068,18 +1068,19 @@
 		if (syserror(tcp)) {
 			tprintf("%#lx", tcp->u_arg[0]);
 		} else {
-#if !defined(SPARC) && !defined(SPARC64) && !defined(SH) && !defined(IA64)
-			int fds[2];
-
-			if (umoven(tcp, tcp->u_arg[0], sizeof fds, (char *) fds) < 0)
-				tprints("[...]");
-			else
-				tprintf("[%u, %u]", fds[0], fds[1]);
-#elif defined(SPARC) || defined(SPARC64) || defined(SH) || defined(IA64)
-			tprintf("[%lu, %lu]", tcp->u_rval, getrval2(tcp));
-#else
-			tprintf("%#lx", tcp->u_arg[0]);
+#ifdef HAVE_GETRVAL2
+			if (flags_arg < 0) {
+				tprintf("[%lu, %lu]", tcp->u_rval, getrval2(tcp));
+			} else
 #endif
+			{
+				int fds[2];
+
+				if (umove(tcp, tcp->u_arg[0], &fds) < 0)
+					tprintf("%#lx", tcp->u_arg[0]);
+				else
+					tprintf("[%u, %u]", fds[0], fds[1]);
+			}
 		}
 		if (flags_arg >= 0) {
 			tprints(", ");
@@ -1116,7 +1117,7 @@
 			tprintf(", %#lx", tcp->u_arg[3]);
 			return 0;
 		}
-		if (umoven(tcp, tcp->u_arg[3], sizeof fds, (char *) fds) < 0)
+		if (umoven(tcp, tcp->u_arg[3], sizeof fds, fds) < 0)
 			tprints(", [...]");
 		else
 			tprintf(", [%u, %u]", fds[0], fds[1]);
diff --git a/open.c b/open.c
index e97be42..5d82981 100644
--- a/open.c
+++ b/open.c
@@ -120,24 +120,3 @@
 	}
 	return RVAL_FD;
 }
-
-#if defined(SPARC) || defined(SPARC64)
-# include "xlat/openmodessol.h"
-
-int
-solaris_open(struct tcb *tcp)
-{
-	if (entering(tcp)) {
-		printpath(tcp, tcp->u_arg[0]);
-		tprints(", ");
-		/* flags */
-		printflags(openmodessol, tcp->u_arg[1] + 1, "O_???");
-		if (tcp->u_arg[1] & 0x100) {
-			/* mode */
-			tprintf(", %#lo", tcp->u_arg[2]);
-		}
-	}
-	return 0;
-}
-
-#endif /* SPARC || SPARC64 */
diff --git a/pathtrace.c b/pathtrace.c
index 28fc7c9..0db7fe3 100644
--- a/pathtrace.c
+++ b/pathtrace.c
@@ -270,7 +270,7 @@
 		args = tcp->u_arg;
 		if (s->sys_func == sys_oldselect) {
 			if (umoven(tcp, tcp->u_arg[0], sizeof oldargs,
-				   (char*) oldargs) < 0)
+				   oldargs) < 0)
 			{
 				fprintf(stderr, "umoven() failed\n");
 				return 0;
@@ -294,7 +294,7 @@
 		for (i = 1; i <= 3; ++i) {
 			if (args[i] == 0)
 				continue;
-			if (umoven(tcp, args[i], fdsize, (char *) fds) < 0) {
+			if (umoven(tcp, args[i], fdsize, fds) < 0) {
 				fprintf(stderr, "umoven() failed\n");
 				continue;
 			}
@@ -328,7 +328,7 @@
 			return 0;
 
 		for (cur = start; cur < end; cur += sizeof(fds))
-			if ((umoven(tcp, cur, sizeof fds, (char *) &fds) == 0)
+			if ((umoven(tcp, cur, sizeof fds, &fds) == 0)
 			    && fdmatch(tcp, fds.fd))
 				return 1;
 
diff --git a/printmode.c b/printmode.c
index 4df1b9f..a721936 100644
--- a/printmode.c
+++ b/printmode.c
@@ -1,6 +1,7 @@
 #include "defs.h"
 
 #include <fcntl.h>
+#include <sys/stat.h>
 
 #include "xlat/modetypes.h"
 
diff --git a/printsiginfo.c b/printsiginfo.c
new file mode 100644
index 0000000..4e23453
--- /dev/null
+++ b/printsiginfo.c
@@ -0,0 +1,201 @@
+#include "defs.h"
+
+#include "xlat/sigbus_codes.h"
+#include "xlat/sigchld_codes.h"
+#include "xlat/sigfpe_codes.h"
+#include "xlat/sigill_codes.h"
+#include "xlat/siginfo_codes.h"
+#include "xlat/sigpoll_codes.h"
+#include "xlat/sigprof_codes.h"
+#include "xlat/sigsegv_codes.h"
+#include "xlat/sigsys_codes.h"
+#include "xlat/sigtrap_codes.h"
+
+#ifdef SIGEMT
+# include "xlat/sigemt_codes.h"
+#endif
+
+#ifndef SI_FROMUSER
+# define SI_FROMUSER(sip)	((sip)->si_code <= 0)
+#endif
+
+static void
+printsigsource(const siginfo_t *sip)
+{
+	tprintf(", si_pid=%lu, si_uid=%lu",
+		(unsigned long) sip->si_pid,
+		(unsigned long) sip->si_uid);
+}
+
+static void
+printsigval(const siginfo_t *sip, bool verbose)
+{
+	if (!verbose)
+		tprints(", ...");
+	else
+		tprintf(", si_value={int=%u, ptr=%#lx}",
+			sip->si_int,
+			(unsigned long) sip->si_ptr);
+}
+
+static void
+print_si_code(int si_signo, int si_code)
+{
+	const char *code = xlookup(siginfo_codes, si_code);
+
+	if (!code) {
+		switch (si_signo) {
+		case SIGTRAP:
+			code = xlookup(sigtrap_codes, si_code);
+			break;
+		case SIGCHLD:
+			code = xlookup(sigchld_codes, si_code);
+			break;
+		case SIGPOLL:
+			code = xlookup(sigpoll_codes, si_code);
+			break;
+		case SIGPROF:
+			code = xlookup(sigprof_codes, si_code);
+			break;
+		case SIGILL:
+			code = xlookup(sigill_codes, si_code);
+			break;
+#ifdef SIGEMT
+		case SIGEMT:
+			code = xlookup(sigemt_codes, si_code);
+			break;
+#endif
+		case SIGFPE:
+			code = xlookup(sigfpe_codes, si_code);
+			break;
+		case SIGSEGV:
+			code = xlookup(sigsegv_codes, si_code);
+			break;
+		case SIGBUS:
+			code = xlookup(sigbus_codes, si_code);
+			break;
+		case SIGSYS:
+			code = xlookup(sigsys_codes, si_code);
+			break;
+		}
+	}
+
+	if (code)
+		tprints(code);
+	else
+		tprintf("%#x", si_code);
+}
+
+static void
+print_si_info(const siginfo_t *sip, bool verbose)
+{
+	if (sip->si_errno) {
+		tprints(", si_errno=");
+		if ((unsigned) sip->si_errno < nerrnos
+		    && errnoent[sip->si_errno])
+			tprints(errnoent[sip->si_errno]);
+		else
+			tprintf("%d", sip->si_errno);
+	}
+
+	if (SI_FROMUSER(sip)) {
+		switch (sip->si_code) {
+		case SI_USER:
+			printsigsource(sip);
+			break;
+		case SI_TKILL:
+			printsigsource(sip);
+			break;
+#if defined HAVE_SIGINFO_T_SI_TIMERID && defined HAVE_SIGINFO_T_SI_OVERRUN
+		case SI_TIMER:
+			tprintf(", si_timerid=%#x, si_overrun=%d",
+				sip->si_timerid, sip->si_overrun);
+			printsigval(sip, verbose);
+			break;
+#endif
+		default:
+			printsigsource(sip);
+			if (sip->si_ptr)
+				printsigval(sip, verbose);
+			break;
+		}
+	} else {
+		switch (sip->si_signo) {
+		case SIGCHLD:
+			printsigsource(sip);
+			tprints(", si_status=");
+			if (sip->si_code == CLD_EXITED)
+				tprintf("%d", sip->si_status);
+			else
+				printsignal(sip->si_status);
+			if (!verbose)
+				tprints(", ...");
+			else
+				tprintf(", si_utime=%llu, si_stime=%llu",
+					(unsigned long long) sip->si_utime,
+					(unsigned long long) sip->si_stime);
+			break;
+		case SIGILL: case SIGFPE:
+		case SIGSEGV: case SIGBUS:
+			tprintf(", si_addr=%#lx",
+				(unsigned long) sip->si_addr);
+			break;
+		case SIGPOLL:
+			switch (sip->si_code) {
+			case POLL_IN: case POLL_OUT: case POLL_MSG:
+				tprintf(", si_band=%ld",
+					(long) sip->si_band);
+				break;
+			}
+			break;
+#ifdef HAVE_SIGINFO_T_SI_SYSCALL
+		case SIGSYS:
+			tprintf(", si_call_addr=%#lx, si_syscall=%d, si_arch=%u",
+				(unsigned long) sip->si_call_addr,
+				sip->si_syscall, sip->si_arch);
+			break;
+#endif
+		default:
+			if (sip->si_pid || sip->si_uid)
+				printsigsource(sip);
+			if (sip->si_ptr)
+				printsigval(sip, verbose);
+		}
+	}
+}
+
+void
+printsiginfo(const siginfo_t *sip, bool verbose)
+{
+	if (sip->si_signo == 0) {
+		tprints("{}");
+		return;
+	}
+	tprints("{si_signo=");
+	printsignal(sip->si_signo);
+
+	tprints(", si_code=");
+	print_si_code(sip->si_signo, sip->si_code);
+
+#ifdef SI_NOINFO
+	if (sip->si_code != SI_NOINFO)
+#endif
+		print_si_info(sip, verbose);
+
+	tprints("}");
+}
+
+void
+printsiginfo_at(struct tcb *tcp, long addr)
+{
+	siginfo_t si;
+	if (!addr) {
+		tprints("NULL");
+		return;
+	}
+	if (syserror(tcp) || umove(tcp, addr, &si) < 0) {
+		tprintf("%#lx", addr);
+		return;
+	}
+	printsiginfo(&si, verbose(tcp));
+}
diff --git a/process_vm.c b/process_vm.c
index 9bd85a8..02058a5 100644
--- a/process_vm.c
+++ b/process_vm.c
@@ -35,17 +35,11 @@
 		/* arg 1: pid */
 		tprintf("%ld, ", tcp->u_arg[0]);
 		/* arg 2: local iov */
-		if (syserror(tcp))
-			tprintf("%#lx", tcp->u_arg[1]);
-		else
-			tprint_iov(tcp, tcp->u_arg[2], tcp->u_arg[1], 1);
+		tprint_iov(tcp, tcp->u_arg[2], tcp->u_arg[1], 1);
 		/* arg 3: local iovcnt */
 		tprintf(", %lu, ", tcp->u_arg[2]);
 		/* arg 4: remote iov */
-		if (syserror(tcp))
-			tprintf("%#lx", tcp->u_arg[3]);
-		else
-			tprint_iov(tcp, tcp->u_arg[4], tcp->u_arg[3], 0);
+		tprint_iov(tcp, tcp->u_arg[4], tcp->u_arg[3], 0);
 		/* arg 5: remote iovcnt */
 		/* arg 6: flags */
 		tprintf(", %lu, %lu", tcp->u_arg[4], tcp->u_arg[5]);
diff --git a/qemu_multiarch_testing/README b/qemu_multiarch_testing/README
index 3dc5581..9e4ef00 100644
--- a/qemu_multiarch_testing/README
+++ b/qemu_multiarch_testing/README
@@ -39,3 +39,11 @@
 system-image-m68k    - qemu-system-m68k: -M q800: Unsupported machine type
 system-image-mips64  - init dies before reaching /mnt/init
 system-image-sh4     - hdc does not mount (no support for 2 disks)
+
+
+To debug a build problem in one of sandboxes, change keep_hdb
+to "keep_hdb=true" in parallel-build-hdc-img.sh
+
+This preserves system-image-DIR1/hdb.img after the build,
+so you can go into system-image-DIR1 and run
+"HDB=hdb.img ./dev-environment.sh" to debug the problem.
diff --git a/qemu_multiarch_testing/parallel-build-hdc-img.sh b/qemu_multiarch_testing/parallel-build-hdc-img.sh
index d98f954..8d27367 100755
--- a/qemu_multiarch_testing/parallel-build-hdc-img.sh
+++ b/qemu_multiarch_testing/parallel-build-hdc-img.sh
@@ -1,13 +1,14 @@
 #!/bin/sh
 
 export HDBMEGS=64
+keep_hdb=false
 
 build_in_dir()
 {
 	cd "$1" || exit 1
 	rm -f hdb.img
 	nice -n10 time ./native-build.sh ../hdc.img
-	rm -f hdb.img
+	$keep_hdb || rm -f hdb.img
 	echo >&3 "Finished: $1"
 }
 
diff --git a/scsi.c b/scsi.c
index 867b74c..73c97ea 100644
--- a/scsi.c
+++ b/scsi.c
@@ -53,7 +53,7 @@
 		goto out;
 	allocated = (len > max_strlen) ? max_strlen : len;
 	if ((buf = malloc(allocated)) == NULL ||
-	    umoven(tcp, addr, allocated, (char *) buf) < 0) {
+	    umoven(tcp, addr, allocated, buf) < 0) {
 		tprintf("%#lx", addr);
 		goto out;
 	}
diff --git a/sigaltstack.c b/sigaltstack.c
new file mode 100644
index 0000000..feba59b
--- /dev/null
+++ b/sigaltstack.c
@@ -0,0 +1,53 @@
+#include "defs.h"
+#include "xlat/sigaltstack_flags.h"
+
+static void
+print_stack_t(struct tcb *tcp, unsigned long addr)
+{
+	stack_t ss;
+	int r;
+
+	if (!addr) {
+		tprints("NULL");
+		return;
+	}
+
+#if SUPPORTED_PERSONALITIES > 1 && SIZEOF_LONG > 4
+	if (current_wordsize != sizeof(ss.ss_sp) && current_wordsize == 4) {
+		struct {
+			uint32_t ss_sp;
+			int32_t ss_flags;
+			uint32_t ss_size;
+		} ss32;
+		r = umove(tcp, addr, &ss32);
+		if (r >= 0) {
+			memset(&ss, 0, sizeof(ss));
+			ss.ss_sp = (void*)(unsigned long) ss32.ss_sp;
+			ss.ss_flags = ss32.ss_flags;
+			ss.ss_size = (unsigned long) ss32.ss_size;
+		}
+	} else
+#endif
+	{
+		r = umove(tcp, addr, &ss);
+	}
+	if (r < 0) {
+		tprintf("%#lx", addr);
+	} else {
+		tprintf("{ss_sp=%#lx, ss_flags=", (unsigned long) ss.ss_sp);
+		printflags(sigaltstack_flags, ss.ss_flags, "SS_???");
+		tprintf(", ss_size=%lu}", (unsigned long) ss.ss_size);
+	}
+}
+
+int
+sys_sigaltstack(struct tcb *tcp)
+{
+	if (entering(tcp)) {
+		print_stack_t(tcp, tcp->u_arg[0]);
+	} else {
+		tprints(", ");
+		print_stack_t(tcp, tcp->u_arg[1]);
+	}
+	return 0;
+}
diff --git a/signal.c b/signal.c
index 867e156..0b52ddb 100644
--- a/signal.c
+++ b/signal.c
@@ -249,258 +249,6 @@
 	tprints(sprintsigmask_n("", mask, len));
 }
 
-#ifndef ILL_ILLOPC
-#define ILL_ILLOPC      1       /* illegal opcode */
-#define ILL_ILLOPN      2       /* illegal operand */
-#define ILL_ILLADR      3       /* illegal addressing mode */
-#define ILL_ILLTRP      4       /* illegal trap */
-#define ILL_PRVOPC      5       /* privileged opcode */
-#define ILL_PRVREG      6       /* privileged register */
-#define ILL_COPROC      7       /* coprocessor error */
-#define ILL_BADSTK      8       /* internal stack error */
-#define FPE_INTDIV      1       /* integer divide by zero */
-#define FPE_INTOVF      2       /* integer overflow */
-#define FPE_FLTDIV      3       /* floating point divide by zero */
-#define FPE_FLTOVF      4       /* floating point overflow */
-#define FPE_FLTUND      5       /* floating point underflow */
-#define FPE_FLTRES      6       /* floating point inexact result */
-#define FPE_FLTINV      7       /* floating point invalid operation */
-#define FPE_FLTSUB      8       /* subscript out of range */
-#define SEGV_MAPERR     1       /* address not mapped to object */
-#define SEGV_ACCERR     2       /* invalid permissions for mapped object */
-#define BUS_ADRALN      1       /* invalid address alignment */
-#define BUS_ADRERR      2       /* non-existant physical address */
-#define BUS_OBJERR      3       /* object specific hardware error */
-#define SYS_SECCOMP     1       /* seccomp triggered */
-#define TRAP_BRKPT      1       /* process breakpoint */
-#define TRAP_TRACE      2       /* process trace trap */
-#define CLD_EXITED      1       /* child has exited */
-#define CLD_KILLED      2       /* child was killed */
-#define CLD_DUMPED      3       /* child terminated abnormally */
-#define CLD_TRAPPED     4       /* traced child has trapped */
-#define CLD_STOPPED     5       /* child has stopped */
-#define CLD_CONTINUED   6       /* stopped child has continued */
-#define POLL_IN         1       /* data input available */
-#define POLL_OUT        2       /* output buffers available */
-#define POLL_MSG        3       /* input message available */
-#define POLL_ERR        4       /* i/o error */
-#define POLL_PRI        5       /* high priority input available */
-#define POLL_HUP        6       /* device disconnected */
-#define SI_KERNEL	0x80	/* sent by kernel */
-#define SI_USER         0       /* sent by kill, sigsend, raise */
-#define SI_QUEUE        -1      /* sent by sigqueue */
-#define SI_TIMER        -2      /* sent by timer expiration */
-#define SI_MESGQ        -3      /* sent by real time mesq state change */
-#define SI_ASYNCIO      -4      /* sent by AIO completion */
-#define SI_SIGIO	-5	/* sent by SIGIO */
-#define SI_TKILL	-6	/* sent by tkill */
-#define SI_DETHREAD	-7	/* sent by execve killing subsidiary threads */
-#define SI_ASYNCNL	-60     /* sent by asynch name lookup completion */
-#endif
-
-#ifndef SI_FROMUSER
-# define SI_FROMUSER(sip)	((sip)->si_code <= 0)
-#endif
-
-#include "xlat/siginfo_codes.h"
-#include "xlat/sigill_codes.h"
-#include "xlat/sigfpe_codes.h"
-#include "xlat/sigtrap_codes.h"
-#include "xlat/sigchld_codes.h"
-#include "xlat/sigpoll_codes.h"
-#include "xlat/sigprof_codes.h"
-
-#ifdef SIGEMT
-#include "xlat/sigemt_codes.h"
-#endif
-
-#include "xlat/sigsegv_codes.h"
-#include "xlat/sigbus_codes.h"
-
-#ifndef SYS_SECCOMP
-# define SYS_SECCOMP 1
-#endif
-#include "xlat/sigsys_codes.h"
-
-static void
-printsigsource(const siginfo_t *sip)
-{
-	tprintf(", si_pid=%lu, si_uid=%lu",
-		(unsigned long) sip->si_pid,
-		(unsigned long) sip->si_uid);
-}
-
-static void
-printsigval(const siginfo_t *sip, int verbose)
-{
-	if (!verbose)
-		tprints(", ...");
-	else
-		tprintf(", si_value={int=%u, ptr=%#lx}",
-			sip->si_int,
-			(unsigned long) sip->si_ptr);
-}
-
-void
-printsiginfo(const siginfo_t *sip, int verbose)
-{
-	const char *code;
-
-	if (sip->si_signo == 0) {
-		tprints("{}");
-		return;
-	}
-	tprints("{si_signo=");
-	printsignal(sip->si_signo);
-	code = xlookup(siginfo_codes, sip->si_code);
-	if (!code) {
-		switch (sip->si_signo) {
-		case SIGTRAP:
-			code = xlookup(sigtrap_codes, sip->si_code);
-			break;
-		case SIGCHLD:
-			code = xlookup(sigchld_codes, sip->si_code);
-			break;
-		case SIGPOLL:
-			code = xlookup(sigpoll_codes, sip->si_code);
-			break;
-		case SIGPROF:
-			code = xlookup(sigprof_codes, sip->si_code);
-			break;
-		case SIGILL:
-			code = xlookup(sigill_codes, sip->si_code);
-			break;
-#ifdef SIGEMT
-		case SIGEMT:
-			code = xlookup(sigemt_codes, sip->si_code);
-			break;
-#endif
-		case SIGFPE:
-			code = xlookup(sigfpe_codes, sip->si_code);
-			break;
-		case SIGSEGV:
-			code = xlookup(sigsegv_codes, sip->si_code);
-			break;
-		case SIGBUS:
-			code = xlookup(sigbus_codes, sip->si_code);
-			break;
-		case SIGSYS:
-			code = xlookup(sigsys_codes, sip->si_code);
-			break;
-		}
-	}
-	if (code)
-		tprintf(", si_code=%s", code);
-	else
-		tprintf(", si_code=%#x", sip->si_code);
-#ifdef SI_NOINFO
-	if (sip->si_code != SI_NOINFO)
-#endif
-	{
-		if (sip->si_errno) {
-			tprints(", si_errno=");
-			if ((unsigned) sip->si_errno < nerrnos
-			    && errnoent[sip->si_errno])
-				tprints(errnoent[sip->si_errno]);
-			else
-				tprintf("%d", sip->si_errno);
-		}
-#ifdef SI_FROMUSER
-		if (SI_FROMUSER(sip)) {
-			switch (sip->si_code) {
-#ifdef SI_USER
-			case SI_USER:
-				printsigsource(sip);
-				break;
-#endif
-#ifdef SI_TKILL
-			case SI_TKILL:
-				printsigsource(sip);
-				break;
-#endif
-#if defined SI_TIMER \
- && defined HAVE_SIGINFO_T_SI_TIMERID && defined HAVE_SIGINFO_T_SI_OVERRUN
-			case SI_TIMER:
-				tprintf(", si_timerid=%#x, si_overrun=%d",
-					sip->si_timerid, sip->si_overrun);
-				printsigval(sip, verbose);
-				break;
-#endif
-			default:
-				printsigsource(sip);
-				if (sip->si_ptr)
-					printsigval(sip, verbose);
-				break;
-			}
-		}
-		else
-#endif /* SI_FROMUSER */
-		{
-			switch (sip->si_signo) {
-			case SIGCHLD:
-				printsigsource(sip);
-				tprints(", si_status=");
-				if (sip->si_code == CLD_EXITED)
-					tprintf("%d", sip->si_status);
-				else
-					printsignal(sip->si_status);
-				if (!verbose)
-					tprints(", ...");
-				else
-					tprintf(", si_utime=%llu, si_stime=%llu",
-						(unsigned long long) sip->si_utime,
-						(unsigned long long) sip->si_stime);
-				break;
-			case SIGILL: case SIGFPE:
-			case SIGSEGV: case SIGBUS:
-				tprintf(", si_addr=%#lx",
-					(unsigned long) sip->si_addr);
-				break;
-			case SIGPOLL:
-				switch (sip->si_code) {
-				case POLL_IN: case POLL_OUT: case POLL_MSG:
-					tprintf(", si_band=%ld",
-						(long) sip->si_band);
-					break;
-				}
-				break;
-#ifdef HAVE_SIGINFO_T_SI_SYSCALL
-			case SIGSYS:
-				tprintf(", si_call_addr=%#lx, si_syscall=%d, si_arch=%u",
-					(unsigned long) sip->si_call_addr,
-					sip->si_syscall, sip->si_arch);
-				break;
-#endif
-			default:
-				if (sip->si_pid || sip->si_uid)
-				        printsigsource(sip);
-				if (sip->si_ptr)
-					printsigval(sip, verbose);
-			}
-		}
-	}
-	tprints("}");
-}
-
-void
-printsiginfo_at(struct tcb *tcp, long addr)
-{
-	siginfo_t si;
-	if (!addr) {
-		tprints("NULL");
-		return;
-	}
-	if (syserror(tcp)) {
-		tprintf("%#lx", addr);
-		return;
-	}
-	if (umove(tcp, addr, &si) < 0) {
-		tprints("{???}");
-		return;
-	}
-	printsiginfo(&si, verbose(tcp));
-}
-
 int
 sys_sigsetmask(struct tcb *tcp)
 {
@@ -681,65 +429,6 @@
 	return 0;
 }
 
-#if !defined SS_ONSTACK
-#define SS_ONSTACK      1
-#define SS_DISABLE      2
-#endif
-
-#include "xlat/sigaltstack_flags.h"
-
-static void
-print_stack_t(struct tcb *tcp, unsigned long addr)
-{
-	stack_t ss;
-	int r;
-
-	if (!addr) {
-		tprints("NULL");
-		return;
-	}
-
-#if SUPPORTED_PERSONALITIES > 1 && SIZEOF_LONG > 4
-	if (current_wordsize != sizeof(ss.ss_sp) && current_wordsize == 4) {
-		struct {
-			uint32_t ss_sp;
-			int32_t ss_flags;
-			uint32_t ss_size;
-		} ss32;
-		r = umove(tcp, addr, &ss32);
-		if (r >= 0) {
-			memset(&ss, 0, sizeof(ss));
-			ss.ss_sp = (void*)(unsigned long) ss32.ss_sp;
-			ss.ss_flags = ss32.ss_flags;
-			ss.ss_size = (unsigned long) ss32.ss_size;
-		}
-	} else
-#endif
-	{
-		r = umove(tcp, addr, &ss);
-	}
-	if (r < 0) {
-		tprintf("%#lx", addr);
-	} else {
-		tprintf("{ss_sp=%#lx, ss_flags=", (unsigned long) ss.ss_sp);
-		printflags(sigaltstack_flags, ss.ss_flags, "SS_???");
-		tprintf(", ss_size=%lu}", (unsigned long) ss.ss_size);
-	}
-}
-
-int
-sys_sigaltstack(struct tcb *tcp)
-{
-	if (entering(tcp)) {
-		print_stack_t(tcp, tcp->u_arg[0]);
-	}
-	else {
-		tprints(", ");
-		print_stack_t(tcp, tcp->u_arg[1]);
-	}
-	return 0;
-}
-
 #ifdef HAVE_SIGACTION
 
 /* "Old" sigprocmask, which operates with word-sized signal masks */
@@ -1056,8 +745,13 @@
 int
 sys_restart_syscall(struct tcb *tcp)
 {
-	if (entering(tcp))
-		tprints("<... resuming interrupted call ...>");
+	if (entering(tcp)) {
+		tprintf("<... resuming interrupted %s ...>",
+			tcp->s_prev_ent
+			? tcp->s_prev_ent->sys_name
+			: "system call"
+		);
+	}
 	return 0;
 }
 
diff --git a/sigreturn.c b/sigreturn.c
index 365ef1a..b3fc038 100644
--- a/sigreturn.c
+++ b/sigreturn.c
@@ -16,228 +16,8 @@
 int
 sys_sigreturn(struct tcb *tcp)
 {
-#if defined AARCH64 || defined ARM
 	if (entering(tcp)) {
-# define SIZEOF_STRUCT_SIGINFO 128
-# define SIZEOF_STRUCT_SIGCONTEXT (21 * 4)
-# define OFFSETOF_STRUCT_UCONTEXT_UC_SIGMASK (5 * 4 + SIZEOF_STRUCT_SIGCONTEXT)
-		const long addr =
-# ifdef AARCH64
-			current_personality == 1 ?
-				(*aarch64_sp_ptr + SIZEOF_STRUCT_SIGINFO +
-				 offsetof(struct ucontext, uc_sigmask)) :
-# endif
-				(*arm_sp_ptr +
-				 OFFSETOF_STRUCT_UCONTEXT_UC_SIGMASK);
-		tprints("{mask=");
-		print_sigset_addr_len(tcp, addr, NSIG / 8);
-		tprints("}");
+#include "arch_sigreturn.c"
 	}
-#elif defined(S390) || defined(S390X)
-	if (entering(tcp)) {
-		long mask[NSIG / 8 / sizeof(long)];
-		tprints("{mask=");
-		const long addr = *s390_frame_ptr + __SIGNAL_FRAMESIZE;
-		if (umove(tcp, addr, &mask) < 0) {
-			tprintf("%#lx", addr);
-		} else {
-# ifdef S390
-			long v = mask[0];
-			mask[0] = mask[1];
-			mask[1] = v;
-# endif
-			tprintsigmask_addr("", mask);
-		}
-		tprints("}");
-	}
-#elif defined I386 || defined X86_64 || defined X32
-	if (entering(tcp)) {
-# ifndef I386
-		if (current_personality != 1) {
-			const unsigned long addr =
-				(unsigned long) *x86_64_rsp_ptr +
-				offsetof(struct ucontext, uc_sigmask);
-			tprints("{mask=");
-			print_sigset_addr_len(tcp, addr, NSIG / 8);
-			tprints("}");
-			return 0;
-		}
-# endif
-		/*
-		 * On i386, sigcontext is followed on stack by struct fpstate
-		 * and after it an additional u32 extramask which holds
-		 * upper half of the mask.
-		 */
-		struct {
-			uint32_t struct_sigcontext_padding1[20];
-			uint32_t oldmask;
-			uint32_t struct_sigcontext_padding2;
-			uint32_t struct_fpstate_padding[156];
-			uint32_t extramask;
-		} frame;
-		tprints("{mask=");
-		if (umove(tcp, *i386_esp_ptr, &frame) < 0) {
-			tprintf("%#lx", (unsigned long) *i386_esp_ptr);
-		} else {
-			uint32_t mask[2] = { frame.oldmask, frame.extramask };
-			tprintsigmask_addr("", mask);
-		}
-		tprints("}");
-	}
-#elif defined(IA64)
-	if (entering(tcp)) {
-		/* offsetof(struct sigframe, sc) */
-#		define OFFSETOF_STRUCT_SIGFRAME_SC	0xA0
-		const long addr = *ia64_frame_ptr + 16 +
-				  OFFSETOF_STRUCT_SIGFRAME_SC +
-				  offsetof(struct sigcontext, sc_mask);
-		tprints("{mask=");
-		print_sigset_addr_len(tcp, addr, NSIG / 8);
-		tprints("}");
-	}
-#elif defined(POWERPC)
-	if (entering(tcp)) {
-		long esp = ppc_regs.gpr[1];
-		struct sigcontext sc;
-
-		/* Skip dummy stack frame. */
-#ifdef POWERPC64
-		if (current_personality == 0)
-			esp += 128;
-		else
-#endif
-			esp += 64;
-
-		tprints("{mask=");
-		if (umove(tcp, esp, &sc) < 0) {
-			tprintf("%#lx", esp);
-		} else {
-			unsigned long mask[NSIG / 8 / sizeof(long)];
-#ifdef POWERPC64
-			mask[0] = sc.oldmask | (sc._unused[3] << 32);
-#else
-			mask[0] = sc.oldmask;
-			mask[1] = sc._unused[3];
-#endif
-			tprintsigmask_addr("", mask);
-		}
-		tprints("}");
-	}
-#elif defined(M68K)
-	if (entering(tcp)) {
-		long addr;
-		if (upeek(tcp->pid, 4*PT_USP, &addr) < 0)
-			return 0;
-		/* Fetch pointer to struct sigcontext.  */
-		if (umove(tcp, addr + 2 * sizeof(int), &addr) < 0)
-			return 0;
-		unsigned long mask[NSIG / 8 / sizeof(long)];
-		/* Fetch first word of signal mask.  */
-		if (umove(tcp, addr, &mask[0]) < 0)
-			return 0;
-		/* Fetch remaining words of signal mask, located
-		   immediately before.  */
-		addr -= sizeof(mask) - sizeof(long);
-		if (umoven(tcp, addr, sizeof(mask) - sizeof(long), (char *) &mask[1]) < 0)
-			return 0;
-		tprints("{mask=");
-		tprintsigmask_addr("", mask);
-		tprints("}");
-	}
-#elif defined(ALPHA)
-	if (entering(tcp)) {
-		long addr;
-		if (upeek(tcp->pid, REG_FP, &addr) < 0)
-			return 0;
-		addr += offsetof(struct sigcontext, sc_mask);
-		tprints("{mask=");
-		print_sigset_addr_len(tcp, addr, NSIG / 8);
-		tprints("}");
-	}
-#elif defined(SPARC) || defined(SPARC64)
-	if (entering(tcp)) {
-		long fp = sparc_regs.u_regs[U_REG_FP] + sizeof(struct sparc_stackf);
-		struct {
-			struct pt_regs si_regs;
-			int si_mask;
-			void *fpu_save;
-			long insns[2] __attribute__ ((aligned (8)));
-			unsigned int extramask[NSIG / 8 / sizeof(int) - 1];
-		} frame;
-
-		tprints("{mask=");
-		if (umove(tcp, fp, &frame) < 0) {
-			tprintf("%#lx", fp);
-		} else {
-			unsigned int mask[NSIG / 8 / sizeof(int)];
-
-			mask[0] = frame.si_mask;
-			memcpy(mask + 1, frame.extramask, sizeof(frame.extramask));
-			tprintsigmask_addr("", mask);
-		}
-		tprints("}");
-	}
-#elif defined MIPS
-	if (entering(tcp)) {
-# if defined LINUX_MIPSO32
-		/*
-		 * offsetof(struct sigframe, sf_mask) ==
-		 * sizeof(sf_ass) + sizeof(sf_pad) + sizeof(struct sigcontext)
-		 */
-		const long addr = mips_REG_SP + 6 * 4 +
-				  sizeof(struct sigcontext);
-# else
-		/*
-		 * This decodes rt_sigreturn.
-		 * The 64-bit ABIs do not have sigreturn.
-		 *
-		 * offsetof(struct rt_sigframe, rs_uc) ==
-		 * sizeof(sf_ass) + sizeof(sf_pad) + sizeof(struct siginfo)
-		 */
-		const long addr = mips_REG_SP + 6 * 4 + 128 +
-				  offsetof(struct ucontext, uc_sigmask);
-# endif
-		tprints("{mask=");
-		print_sigset_addr_len(tcp, addr, NSIG / 8);
-		tprints("}");
-	}
-#elif defined(CRISV10) || defined(CRISV32)
-	if (entering(tcp)) {
-		long regs[PT_MAX+1];
-		if (ptrace(PTRACE_GETREGS, tcp->pid, NULL, (long)regs) < 0) {
-			perror_msg("sigreturn: PTRACE_GETREGS");
-			return 0;
-		}
-		const long addr = regs[PT_USP] +
-			offsetof(struct sigcontext, oldmask);
-		tprints("{mask=");
-		print_sigset_addr_len(tcp, addr, NSIG / 8);
-		tprints("}");
-	}
-#elif defined(TILE)
-	if (entering(tcp)) {
-		/* offset of ucontext in the kernel's sigframe structure */
-# define SIGFRAME_UC_OFFSET C_ABI_SAVE_AREA_SIZE + sizeof(siginfo_t)
-		const long addr = tile_regs.sp + SIGFRAME_UC_OFFSET +
-				  offsetof(struct ucontext, uc_sigmask);
-		tprints("{mask=");
-		print_sigset_addr_len(tcp, addr, NSIG / 8);
-		tprints("}");
-	}
-#elif defined(MICROBLAZE)
-	/* TODO: Verify that this is correct...  */
-	if (entering(tcp)) {
-		long addr;
-		/* Read r1, the stack pointer.  */
-		if (upeek(tcp->pid, 1 * 4, &addr) < 0)
-			return 0;
-		addr += offsetof(struct sigcontext, oldmask);
-		tprints("{mask=");
-		print_sigset_addr_len(tcp, addr, NSIG / 8);
-		tprints("}");
-	}
-#else
-# warning sigreturn/rt_sigreturn signal mask decoding is not implemented for this architecture
-#endif
 	return 0;
 }
diff --git a/sock.c b/sock.c
index b6fc95c..dc8febc 100644
--- a/sock.c
+++ b/sock.c
@@ -256,7 +256,7 @@
 			struct ifreq ifra[nifra];
 
 			if (umoven(tcp, (unsigned long) ifc.ifc_buf,
-				sizeof(ifra), (char *) ifra) < 0) {
+				sizeof(ifra), ifra) < 0) {
 				tprintf("%lx}", (unsigned long) ifc.ifc_buf);
 				return 1;
 			}
diff --git a/statfs.c b/statfs.c
index 214e6b2..6373195 100644
--- a/statfs.c
+++ b/statfs.c
@@ -125,7 +125,7 @@
 	uint32_t f_spare[4];
 }
 #if defined AARCH64 || defined X86_64 || defined X32 || defined IA64
-  __attribute__ ((packed, aligned(4)))
+  ATTRIBUTE_PACKED ATTRIBUTE_ALIGNED(4)
 #endif
 ;
 #if defined AARCH64 || defined ARM
diff --git a/strace.c b/strace.c
index b714255..5eab360 100644
--- a/strace.c
+++ b/strace.c
@@ -251,8 +251,8 @@
 	exit(exitval);
 }
 
-static void die(void) __attribute__ ((noreturn));
-static void die(void)
+static void ATTRIBUTE_NORETURN
+die(void)
 {
 	if (strace_tracer_pid == getpid()) {
 		cflag = 0;
@@ -1097,7 +1097,8 @@
 	char *pathname;
 };
 static struct exec_params params_for_tracee;
-static void __attribute__ ((noinline, noreturn))
+
+static void ATTRIBUTE_NOINLINE ATTRIBUTE_NORETURN
 exec_or_die(void)
 {
 	struct exec_params *params = &params_for_tracee;
@@ -1420,7 +1421,7 @@
  * Don't want main() to inline us and defeat the reason
  * we have a separate function.
  */
-static void __attribute__ ((noinline))
+static void ATTRIBUTE_NOINLINE
 init(int argc, char *argv[])
 {
 	struct tcb *tcp;
@@ -2005,7 +2006,7 @@
 	}
 }
 
-static bool
+static void
 startup_tcb(struct tcb *tcp)
 {
 	if (debug_flag)
@@ -2025,8 +2026,6 @@
 			}
 		}
 	}
-
-	return true;
 }
 
 /* Returns true iff the main trace loop has to continue. */
@@ -2045,8 +2044,26 @@
 	if (interrupted)
 		return false;
 
-	if (popen_pid != 0 && nprocs == 0)
-		return false;
+	/*
+	 * Used to exit simply when nprocs hits zero, but in this testcase:
+	 *  int main() { _exit(!!fork()); }
+	 * under strace -f, parent sometimes (rarely) manages
+	 * to exit before we see the first stop of the child,
+	 * and we are losing track of it:
+	 *  19923 clone(...) = 19924
+	 *  19923 exit_group(1)     = ?
+	 *  19923 +++ exited with 1 +++
+	 * Exiting only when wait() returns ECHILD works better.
+	 */
+	if (popen_pid != 0) {
+		/* However, if -o|logger is in use, we can't do that.
+		 * Can work around that by double-forking the logger,
+		 * but that loses the ability to wait for its completion
+		 * on exit. Oh well...
+		 */
+		if (nprocs == 0)
+			return false;
+	}
 
 	if (interactive)
 		sigprocmask(SIG_SETMASK, &empty_set, NULL);
@@ -2151,8 +2168,9 @@
 
 	/* Is this the very first time we see this tracee stopped? */
 	if (tcp->flags & TCB_STARTUP) {
-		if (!startup_tcb(tcp))
-			return false;
+		startup_tcb(tcp);
+		if (get_scno(tcp) == 1)
+			tcp->s_prev_ent = tcp->s_ent;
 	}
 
 	sig = WSTOPSIG(status);
@@ -2270,23 +2288,6 @@
 {
 	init(argc, argv);
 
-	/*
-	 * Run main tracing loop.
-	 *
-	 * Used to be "while (nprocs != 0)", but in this testcase:
-	 *  int main() { _exit(!!fork()); }
-	 * under strace -f, parent sometimes (rarely) manages
-	 * to exit before we see the first stop of the child,
-	 * and we are losing track of it:
-	 *  19923 clone(...) = 19924
-	 *  19923 exit_group(1)     = ?
-	 *  19923 +++ exited with 1 +++
-	 * Waiting for ECHILD works better.
-	 * (However, if -o|logger is in use, we can't do that.
-	 * Can work around that by double-forking the logger,
-	 * but that loses the ability to wait for its completion on exit.
-	 * Oh well...)
-	 */
 	while (trace())
 		;
 
diff --git a/stream.c b/stream.c
index 2aa6366..3ebbfb7 100644
--- a/stream.c
+++ b/stream.c
@@ -263,7 +263,7 @@
 				tprints("...");
 				break;
 			}
-			if (umoven(tcp, cur, sizeof fds, (char *) &fds) < 0) {
+			if (umoven(tcp, cur, sizeof fds, &fds) < 0) {
 				tprints("?");
 				failed = 1;
 				break;
@@ -313,7 +313,7 @@
 		outptr = outstr;
 
 		for (cur = start; cur < end; cur += sizeof(fds)) {
-			if (umoven(tcp, cur, sizeof fds, (char *) &fds) < 0) {
+			if (umoven(tcp, cur, sizeof fds, &fds) < 0) {
 				if (outptr < end_outstr - 2)
 					*outptr++ = '?';
 				failed = 1;
diff --git a/syscall.c b/syscall.c
index b37f43a..d54d8b6 100644
--- a/syscall.c
+++ b/syscall.c
@@ -559,7 +559,7 @@
 decode_socket_subcall(struct tcb *tcp)
 {
 	unsigned long addr;
-	unsigned int i, n, size;
+	unsigned int n;
 
 	if (tcp->u_arg[0] < 0 || tcp->u_arg[0] >= SYS_socket_nsubcalls)
 		return;
@@ -568,22 +568,18 @@
 	tcp->qual_flg = qual_flags[tcp->scno];
 	tcp->s_ent = &sysent[tcp->scno];
 	addr = tcp->u_arg[1];
-	size = current_wordsize;
 	n = tcp->s_ent->nargs;
-	for (i = 0; i < n; ++i) {
-		if (size == sizeof(int)) {
-			unsigned int arg;
-			if (umove(tcp, addr, &arg) < 0)
-				arg = 0;
-			tcp->u_arg[i] = arg;
-		}
-		else {
-			unsigned long arg;
-			if (umove(tcp, addr, &arg) < 0)
-				arg = 0;
-			tcp->u_arg[i] = arg;
-		}
-		addr += size;
+	if (sizeof(tcp->u_arg[0]) == current_wordsize) {
+		memset(tcp->u_arg, 0, n * sizeof(tcp->u_arg[0]));
+		(void) umoven(tcp, addr, n * sizeof(tcp->u_arg[0]), tcp->u_arg);
+	} else {
+		unsigned int args[n];
+		unsigned int i;
+
+		memset(args, 0, sizeof(args));
+		(void) umove(tcp, addr, &args);
+		for (i = 0; i < n; ++i)
+			tcp->u_arg[i] = args[i];
 	}
 }
 #endif
@@ -642,297 +638,53 @@
 	return 0;
 }
 
-#if defined(I386)
-static struct user_regs_struct i386_regs;
-long *const i386_esp_ptr = &i386_regs.esp;
-# define ARCH_REGS_FOR_GETREGS i386_regs
-#elif defined(X86_64) || defined(X32)
-/*
- * On i386, pt_regs and user_regs_struct are the same,
- * but on 64 bit x86, user_regs_struct has six more fields:
- * fs_base, gs_base, ds, es, fs, gs.
- * PTRACE_GETREGS fills them too, so struct pt_regs would overflow.
- */
-struct i386_user_regs_struct {
-	uint32_t ebx;
-	uint32_t ecx;
-	uint32_t edx;
-	uint32_t esi;
-	uint32_t edi;
-	uint32_t ebp;
-	uint32_t eax;
-	uint32_t xds;
-	uint32_t xes;
-	uint32_t xfs;
-	uint32_t xgs;
-	uint32_t orig_eax;
-	uint32_t eip;
-	uint32_t xcs;
-	uint32_t eflags;
-	uint32_t esp;
-	uint32_t xss;
-};
-static union {
-	struct user_regs_struct      x86_64_r;
-	struct i386_user_regs_struct i386_r;
-} x86_regs_union;
-# define x86_64_regs x86_regs_union.x86_64_r
-# define i386_regs   x86_regs_union.i386_r
-uint32_t *const i386_esp_ptr = &i386_regs.esp;
-uint64_t *const x86_64_rsp_ptr = (uint64_t *) &x86_64_regs.rsp;
-static struct iovec x86_io = {
-	.iov_base = &x86_regs_union
-};
-# define ARCH_REGS_FOR_GETREGSET x86_regs_union
-# define ARCH_IOVEC_FOR_GETREGSET x86_io
-#elif defined(IA64)
-static struct pt_all_user_regs ia64_regs;
-unsigned long *const ia64_frame_ptr = &ia64_regs.gr[12];
-# define IA64_PSR_IS	((long)1 << 34)
-# define ia64_ia32mode	(ia64_regs.cr_ipsr & IA64_PSR_IS)
-# define ARCH_REGS_FOR_GETREGS ia64_regs
-#elif defined(POWERPC)
-struct pt_regs ppc_regs; /* not static */
-# define ARCH_REGS_FOR_GETREGS ppc_regs
-#elif defined(M68K)
-static long m68k_d0;
-#elif defined(BFIN)
-static long bfin_r0;
-#elif defined(ARM)
-static struct pt_regs arm_regs;
-long *const arm_sp_ptr = &arm_regs.ARM_sp;
-# define ARCH_REGS_FOR_GETREGS arm_regs
-#elif defined(AARCH64)
-struct arm_pt_regs {
-        int uregs[18];
-};
-# define ARM_cpsr       uregs[16]
-# define ARM_pc         uregs[15]
-# define ARM_lr         uregs[14]
-# define ARM_sp         uregs[13]
-# define ARM_ip         uregs[12]
-# define ARM_fp         uregs[11]
-# define ARM_r10        uregs[10]
-# define ARM_r9         uregs[9]
-# define ARM_r8         uregs[8]
-# define ARM_r7         uregs[7]
-# define ARM_r6         uregs[6]
-# define ARM_r5         uregs[5]
-# define ARM_r4         uregs[4]
-# define ARM_r3         uregs[3]
-# define ARM_r2         uregs[2]
-# define ARM_r1         uregs[1]
-# define ARM_r0         uregs[0]
-# define ARM_ORIG_r0    uregs[17]
-static union {
-	struct user_pt_regs aarch64_r;
-	struct arm_pt_regs  arm_r;
-} arm_regs_union;
-# define aarch64_regs arm_regs_union.aarch64_r
-# define arm_regs     arm_regs_union.arm_r
-uint64_t *const aarch64_sp_ptr = (uint64_t *) &aarch64_regs.sp;
-uint32_t *const arm_sp_ptr = (uint32_t *) &arm_regs.ARM_sp;
-static struct iovec aarch64_io = {
-	.iov_base = &arm_regs_union
-};
-# define ARCH_REGS_FOR_GETREGSET arm_regs_union
-# define ARCH_IOVEC_FOR_GETREGSET aarch64_io
-#elif defined(ALPHA)
-static long alpha_r0;
-static long alpha_a3;
-#elif defined(AVR32)
-static struct pt_regs avr32_regs;
-# define ARCH_REGS_FOR_GETREGS avr32_regs
-#elif defined(SPARC) || defined(SPARC64)
-struct pt_regs sparc_regs; /* not static */
-# define ARCH_REGS_FOR_GETREGS sparc_regs
-#elif defined(MIPS)
-struct mips_regs mips_regs; /* not static */
-/* PTRACE_GETREGS on MIPS is available since linux v2.6.15. */
-# define ARCH_REGS_FOR_GETREGS mips_regs
-#elif defined(S390) || defined(S390X)
-/* PTRACE_GETREGSET on S390 is available since linux v2.6.27. */
-static struct user_regs_struct s390_regset;
-unsigned long *const s390_frame_ptr = &s390_regset.gprs[15];
-# define ARCH_REGS_FOR_GETREGSET s390_regset
-#elif defined(HPPA)
-static long hppa_r28;
-#elif defined(SH)
-static long sh_r0;
-#elif defined(SH64)
-static long sh64_r9;
-#elif defined(CRISV10) || defined(CRISV32)
-static long cris_r10;
-#elif defined(TILE)
-struct pt_regs tile_regs; /* not static */
-# define ARCH_REGS_FOR_GETREGS tile_regs
-#elif defined(MICROBLAZE)
-static long microblaze_r3;
-#elif defined(OR1K)
-static struct user_regs_struct or1k_regs;
-# define ARCH_REGS_FOR_GETREGSET or1k_regs
-#elif defined(METAG)
-static struct user_gp_regs metag_regs;
-# define ARCH_REGS_FOR_GETREGSET metag_regs
-#elif defined(XTENSA)
-static long xtensa_a2;
-# elif defined(ARC)
-static struct user_regs_struct arc_regs;
-# define ARCH_REGS_FOR_GETREGSET arc_regs
-#endif
-
-static long get_regs_error;
-
-#if defined(SPARC) || defined(SPARC64) || defined(IA64) || defined(SH)
-long
-getrval2(struct tcb *tcp)
+static void
+dumpio(struct tcb *tcp)
 {
-	long val;
+	int (*func)();
 
-# if defined(SPARC) || defined(SPARC64)
-	val = sparc_regs.u_regs[U_REG_O1];
-# elif defined(SH)
-	if (upeek(tcp->pid, 4*(REG_REG0+1), &val) < 0)
-		return -1;
-# elif defined(IA64)
-	val = ia64_regs.gr[9];
-# endif
-
-	return val;
-}
+	if (syserror(tcp))
+		return;
+	if ((unsigned long) tcp->u_arg[0] >= num_quals)
+		return;
+	func = tcp->s_ent->sys_func;
+	if (func == printargs)
+		return;
+	if (qual_flags[tcp->u_arg[0]] & QUAL_READ) {
+		if (func == sys_read ||
+		    func == sys_pread ||
+		    func == sys_recv ||
+		    func == sys_recvfrom) {
+			dumpstr(tcp, tcp->u_arg[1], tcp->u_rval);
+			return;
+		} else if (func == sys_readv) {
+			dumpiov(tcp, tcp->u_arg[2], tcp->u_arg[1]);
+			return;
+#if HAVE_SENDMSG
+		} else if (func == sys_recvmsg) {
+			dumpiov_in_msghdr(tcp, tcp->u_arg[1]);
+			return;
+		} else if (func == sys_recvmmsg) {
+			dumpiov_in_mmsghdr(tcp, tcp->u_arg[1]);
+			return;
 #endif
-
-void
-print_pc(struct tcb *tcp)
-{
-	const char *fmt;
-	const char *bad;
-
-#ifdef current_wordsize
-# define pc_wordsize current_wordsize
-#else
-# define pc_wordsize personality_wordsize[tcp->currpers]
+		}
+	}
+	if (qual_flags[tcp->u_arg[0]] & QUAL_WRITE) {
+		if (func == sys_write ||
+		    func == sys_pwrite ||
+		    func == sys_send ||
+		    func == sys_sendto)
+			dumpstr(tcp, tcp->u_arg[1], tcp->u_arg[2]);
+		else if (func == sys_writev)
+			dumpiov(tcp, tcp->u_arg[2], tcp->u_arg[1]);
+#if HAVE_SENDMSG
+		else if (func == sys_sendmsg)
+			dumpiov_in_msghdr(tcp, tcp->u_arg[1]);
+		else if (func == sys_sendmmsg)
+			dumpiov_in_mmsghdr(tcp, tcp->u_arg[1]);
 #endif
-
-	if (pc_wordsize == 4) {
-		fmt = "[%08lx] ";
-		bad = "[????????] ";
-	} else {
-		fmt = "[%016lx] ";
-		bad = "[????????????????] ";
 	}
-
-#undef pc_wordsize
-#define PRINTBADPC tprints(bad)
-
-	if (get_regs_error) {
-		PRINTBADPC;
-		return;
-	}
-
-#if defined(I386)
-	tprintf(fmt, i386_regs.eip);
-#elif defined(X86_64) || defined(X32)
-	if (x86_io.iov_len == sizeof(i386_regs))
-		tprintf(fmt, (unsigned long) i386_regs.eip);
-	else
-		tprintf(fmt, (unsigned long) x86_64_regs.rip);
-#elif defined(S390) || defined(S390X)
-	tprintf(fmt, s390_regset.psw.addr);
-#elif defined(IA64)
-	tprintf(fmt, ia64_regs.br[0]);
-#elif defined(POWERPC)
-	tprintf(fmt, ppc_regs.nip);
-#elif defined(M68K)
-	long pc;
-	if (upeek(tcp->pid, 4*PT_PC, &pc) < 0) {
-		PRINTBADPC;
-		return;
-	}
-	tprintf(fmt, pc);
-#elif defined(ALPHA)
-	long pc;
-	if (upeek(tcp->pid, REG_PC, &pc) < 0) {
-		PRINTBADPC;
-		return;
-	}
-	tprintf(fmt, pc);
-#elif defined(SPARC)
-	tprintf(fmt, sparc_regs.pc);
-#elif defined(SPARC64)
-	tprintf(fmt, sparc_regs.tpc);
-#elif defined(HPPA)
-	long pc;
-	if (upeek(tcp->pid, PT_IAOQ0, &pc) < 0) {
-		PRINTBADPC;
-		return;
-	}
-	tprintf(fmt, pc);
-#elif defined MIPS
-	tprintf(fmt, (unsigned long) mips_REG_EPC);
-#elif defined(SH)
-	long pc;
-	if (upeek(tcp->pid, 4*REG_PC, &pc) < 0) {
-		PRINTBADPC;
-		return;
-	}
-	tprintf(fmt, pc);
-#elif defined(SH64)
-	long pc;
-	if (upeek(tcp->pid, REG_PC, &pc) < 0) {
-		PRINTBADPC;
-		return;
-	}
-	tprintf(fmt, pc);
-#elif defined(AARCH64)
-	if (aarch64_io.iov_len == sizeof(arm_regs))
-		tprintf(fmt, (unsigned long) arm_regs.ARM_pc);
-	else
-		tprintf(fmt, (unsigned long) aarch64_regs.pc);
-#elif defined(ARM)
-	tprintf(fmt, arm_regs.ARM_pc);
-#elif defined(AVR32)
-	tprintf(fmt, avr32_regs.pc);
-#elif defined(BFIN)
-	long pc;
-	if (upeek(tcp->pid, PT_PC, &pc) < 0) {
-		PRINTBADPC;
-		return;
-	}
-	tprintf(fmt, pc);
-#elif defined(CRISV10)
-	long pc;
-	if (upeek(tcp->pid, 4*PT_IRP, &pc) < 0) {
-		PRINTBADPC;
-		return;
-	}
-	tprintf(fmt, pc);
-#elif defined(CRISV32)
-	long pc;
-	if (upeek(tcp->pid, 4*PT_ERP, &pc) < 0) {
-		PRINTBADPC;
-		return;
-	}
-	tprintf(fmt, pc);
-#elif defined(TILE)
-	tprintf(fmt, (unsigned long) tile_regs.pc);
-#elif defined(OR1K)
-	tprintf(fmt, or1k_regs.pc);
-#elif defined(METAG)
-	tprintf(fmt, metag_regs.pc);
-#elif defined(XTENSA)
-	long pc;
-	if (upeek(tcp->pid, REG_PC, &pc) < 0) {
-		PRINTBADPC;
-		return;
-	}
-	tprintf(fmt, pc);
-#elif defined(ARC)
-	tprintf(fmt, arc_regs.efa);
-#else
-# warning print_pc is not implemented for this architecture
-	PRINTBADPC;
-#endif /* architecture */
 }
 
 /*
@@ -981,42 +733,7 @@
 	return buf;
 }
 
-#ifdef POWERPC
-/*
- * PTRACE_GETREGS was added to the PowerPC kernel in v2.6.23,
- * we provide a slow fallback for old kernels.
- */
-static int powerpc_getregs_old(pid_t pid)
-{
-	int i;
-	long r;
-
-	if (iflag) {
-		r = upeek(pid, sizeof(long) * PT_NIP, (long *)&ppc_regs.nip);
-		if (r)
-			goto out;
-	}
-#ifdef POWERPC64 /* else we never use it */
-	r = upeek(pid, sizeof(long) * PT_MSR, (long *)&ppc_regs.msr);
-	if (r)
-		goto out;
-#endif
-	r = upeek(pid, sizeof(long) * PT_CCR, (long *)&ppc_regs.ccr);
-	if (r)
-		goto out;
-	r = upeek(pid, sizeof(long) * PT_ORIG_R3, (long *)&ppc_regs.orig_gpr3);
-	if (r)
-		goto out;
-	for (i = 0; i <= 8; i++) {
-		r = upeek(pid, sizeof(long) * (PT_R0 + i),
-			  (long *)&ppc_regs.gpr[i]);
-		if (r)
-			goto out;
-	}
- out:
-	return r;
-}
-#endif
+static long get_regs_error;
 
 void
 clear_regs(void)
@@ -1024,736 +741,15 @@
 	get_regs_error = -1;
 }
 
-#if defined ARCH_REGS_FOR_GETREGSET
-static long
-get_regset(pid_t pid)
-{
-# ifdef ARCH_IOVEC_FOR_GETREGSET
-	/* variable iovec */
-	ARCH_IOVEC_FOR_GETREGSET.iov_len = sizeof(ARCH_REGS_FOR_GETREGSET);
-	return ptrace(PTRACE_GETREGSET, pid, NT_PRSTATUS,
-		      &ARCH_IOVEC_FOR_GETREGSET);
-# else
-	/* constant iovec */
-	static struct iovec io = {
-		.iov_base = &ARCH_REGS_FOR_GETREGSET,
-		.iov_len = sizeof(ARCH_REGS_FOR_GETREGSET)
-	};
-	return ptrace(PTRACE_GETREGSET, pid, NT_PRSTATUS, &io);
-
-# endif
-}
-#endif /* ARCH_REGS_FOR_GETREGSET */
-
-void
-get_regs(pid_t pid)
-{
-#ifdef ARCH_REGS_FOR_GETREGSET
-# ifdef X86_64
-	/* Try PTRACE_GETREGSET first, fallback to PTRACE_GETREGS. */
-	static int getregset_support;
-
-	if (getregset_support >= 0) {
-		get_regs_error = get_regset(pid);
-		if (getregset_support > 0)
-			return;
-		if (get_regs_error >= 0) {
-			getregset_support = 1;
-			return;
-		}
-		if (errno == EPERM || errno == ESRCH)
-			return;
-		getregset_support = -1;
-	}
-	/* Use old method, with unreliable heuristical detection of 32-bitness. */
-	x86_io.iov_len = sizeof(x86_64_regs);
-	get_regs_error = ptrace(PTRACE_GETREGS, pid, NULL, &x86_64_regs);
-	if (!get_regs_error && x86_64_regs.cs == 0x23) {
-		x86_io.iov_len = sizeof(i386_regs);
-		/*
-		 * The order is important: i386_regs and x86_64_regs
-		 * are overlaid in memory!
-		 */
-		i386_regs.ebx = x86_64_regs.rbx;
-		i386_regs.ecx = x86_64_regs.rcx;
-		i386_regs.edx = x86_64_regs.rdx;
-		i386_regs.esi = x86_64_regs.rsi;
-		i386_regs.edi = x86_64_regs.rdi;
-		i386_regs.ebp = x86_64_regs.rbp;
-		i386_regs.eax = x86_64_regs.rax;
-		/* i386_regs.xds = x86_64_regs.ds; unused by strace */
-		/* i386_regs.xes = x86_64_regs.es; ditto... */
-		/* i386_regs.xfs = x86_64_regs.fs; */
-		/* i386_regs.xgs = x86_64_regs.gs; */
-		i386_regs.orig_eax = x86_64_regs.orig_rax;
-		i386_regs.eip = x86_64_regs.rip;
-		/* i386_regs.xcs = x86_64_regs.cs; */
-		/* i386_regs.eflags = x86_64_regs.eflags; */
-		i386_regs.esp = x86_64_regs.rsp;
-		/* i386_regs.xss = x86_64_regs.ss; */
-	}
-# else /* !X86_64 */
-	/* Assume that PTRACE_GETREGSET works. */
-	get_regs_error = get_regset(pid);
-# endif
-#elif defined ARCH_REGS_FOR_GETREGS
-# if defined SPARC || defined SPARC64
-	/* SPARC systems have the meaning of data and addr reversed */
-	get_regs_error = ptrace(PTRACE_GETREGS, pid, (char *)&ARCH_REGS_FOR_GETREGS, 0);
-# elif defined POWERPC
-	static bool old_kernel = 0;
-	if (old_kernel)
-		goto old;
-	get_regs_error = ptrace(PTRACE_GETREGS, pid, NULL, &ARCH_REGS_FOR_GETREGS);
-	if (get_regs_error && errno == EIO) {
-		old_kernel = 1;
- old:
-		get_regs_error = powerpc_getregs_old(pid);
-	}
-# else
-	/* Assume that PTRACE_GETREGS works. */
-	get_regs_error = ptrace(PTRACE_GETREGS, pid, NULL, &ARCH_REGS_FOR_GETREGS);
-# endif
-
-#else /* !ARCH_REGS_FOR_GETREGSET && !ARCH_REGS_FOR_GETREGS */
-#  warning get_regs is not implemented for this architecture yet
-	get_regs_error = 0;
-#endif
-}
-
-/* Returns:
- * 0: "ignore this ptrace stop", bail out of trace_syscall_entering() silently.
- * 1: ok, continue in trace_syscall_entering().
- * other: error, trace_syscall_entering() should print error indicator
- *    ("????" etc) and bail out.
- */
-static int
-get_scno(struct tcb *tcp)
-{
-	long scno = 0;
-
-#if defined(S390) || defined(S390X)
-	scno = s390_regset.gprs[2];
-#elif defined(POWERPC)
-	scno = ppc_regs.gpr[0];
-# ifdef POWERPC64
-	unsigned int currpers;
-
-	/*
-	 * Check for 64/32 bit mode.
-	 * Embedded implementations covered by Book E extension of PPC use
-	 * bit 0 (CM) of 32-bit Machine state register (MSR).
-	 * Other implementations use bit 0 (SF) of 64-bit MSR.
-	 */
-	currpers = (ppc_regs.msr & 0x8000000080000000) ? 0 : 1;
-	update_personality(tcp, currpers);
-# endif
-#elif defined(AVR32)
-	scno = avr32_regs.r8;
-#elif defined(BFIN)
-	if (upeek(tcp->pid, PT_ORIG_P0, &scno))
-		return -1;
-#elif defined(I386)
-	scno = i386_regs.orig_eax;
-#elif defined(X86_64) || defined(X32)
-# ifndef __X32_SYSCALL_BIT
-#  define __X32_SYSCALL_BIT	0x40000000
-# endif
-	unsigned int currpers;
-# if 1
-	/* GETREGSET of NT_PRSTATUS tells us regset size,
-	 * which unambiguously detects i386.
-	 *
-	 * Linux kernel distinguishes x86-64 and x32 processes
-	 * solely by looking at __X32_SYSCALL_BIT:
-	 * arch/x86/include/asm/compat.h::is_x32_task():
-	 * if (task_pt_regs(current)->orig_ax & __X32_SYSCALL_BIT)
-	 *         return true;
-	 */
-	if (x86_io.iov_len == sizeof(i386_regs)) {
-		scno = i386_regs.orig_eax;
-		currpers = 1;
-	} else {
-		scno = x86_64_regs.orig_rax;
-		currpers = 0;
-		if (scno & __X32_SYSCALL_BIT) {
-			/*
-			 * Syscall number -1 requires special treatment:
-			 * it might be a side effect of SECCOMP_RET_ERRNO
-			 * filtering that sets orig_rax to -1
-			 * in some versions of linux kernel.
-			 * If that is the case, then
-			 * __X32_SYSCALL_BIT logic does not apply.
-			 */
-			if ((long long) x86_64_regs.orig_rax != -1) {
-				scno -= __X32_SYSCALL_BIT;
-				currpers = 2;
-			} else {
-#  ifdef X32
-				currpers = 2;
-#  endif
-			}
-		}
-	}
-# elif 0
-	/* cs = 0x33 for long mode (native 64 bit and x32)
-	 * cs = 0x23 for compatibility mode (32 bit)
-	 * ds = 0x2b for x32 mode (x86-64 in 32 bit)
-	 */
-	scno = x86_64_regs.orig_rax;
-	switch (x86_64_regs.cs) {
-		case 0x23: currpers = 1; break;
-		case 0x33:
-			if (x86_64_regs.ds == 0x2b) {
-				currpers = 2;
-				scno &= ~__X32_SYSCALL_BIT;
-			} else
-				currpers = 0;
-			break;
-		default:
-			fprintf(stderr, "Unknown value CS=0x%08X while "
-				 "detecting personality of process "
-				 "PID=%d\n", (int)x86_64_regs.cs, tcp->pid);
-			currpers = current_personality;
-			break;
-	}
-# elif 0
-	/* This version analyzes the opcode of a syscall instruction.
-	 * (int 0x80 on i386 vs. syscall on x86-64)
-	 * It works, but is too complicated, and strictly speaking, unreliable.
-	 */
-	unsigned long call, rip = x86_64_regs.rip;
-	/* sizeof(syscall) == sizeof(int 0x80) == 2 */
-	rip -= 2;
-	errno = 0;
-	call = ptrace(PTRACE_PEEKTEXT, tcp->pid, (char *)rip, (char *)0);
-	if (errno)
-		fprintf(stderr, "ptrace_peektext failed: %s\n",
-				strerror(errno));
-	switch (call & 0xffff) {
-		/* x86-64: syscall = 0x0f 0x05 */
-		case 0x050f: currpers = 0; break;
-		/* i386: int 0x80 = 0xcd 0x80 */
-		case 0x80cd: currpers = 1; break;
-		default:
-			currpers = current_personality;
-			fprintf(stderr,
-				"Unknown syscall opcode (0x%04X) while "
-				"detecting personality of process "
-				"PID=%d\n", (int)call, tcp->pid);
-			break;
-	}
-# endif
-
-# ifdef X32
-	/* If we are built for a x32 system, then personality 0 is x32
-	 * (not x86_64), and stracing of x86_64 apps is not supported.
-	 * Stracing of i386 apps is still supported.
-	 */
-	if (currpers == 0) {
-		fprintf(stderr, "syscall_%lu(...) in unsupported "
-				"64-bit mode of process PID=%d\n",
-			scno, tcp->pid);
-		return 0;
-	}
-	currpers &= ~2; /* map 2,1 to 0,1 */
-# endif
-	update_personality(tcp, currpers);
-#elif defined(IA64)
-	if (ia64_ia32mode) {
-		scno = ia64_regs.gr[0];
-	} else {
-		scno = ia64_regs.gr[15];
-	}
-#elif defined(AARCH64)
-	switch (aarch64_io.iov_len) {
-		case sizeof(aarch64_regs):
-			/* We are in 64-bit mode */
-			scno = aarch64_regs.regs[8];
-			update_personality(tcp, 1);
-			break;
-		case sizeof(arm_regs):
-			/* We are in 32-bit mode */
-			/* Note: we don't support OABI, unlike 32-bit ARM build */
-			scno = arm_regs.ARM_r7;
-			scno = shuffle_scno(scno);
-			update_personality(tcp, 0);
-			break;
-	}
-#elif defined(ARM)
-	if (arm_regs.ARM_ip != 0) {
-		/* It is not a syscall entry */
-		fprintf(stderr, "pid %d stray syscall exit\n", tcp->pid);
-		tcp->flags |= TCB_INSYSCALL;
-		return 0;
-	}
-	/* Note: we support only 32-bit CPUs, not 26-bit */
-
-# if !defined(__ARM_EABI__) || ENABLE_ARM_OABI
-	if (arm_regs.ARM_cpsr & 0x20)
-		/* Thumb mode */
-		goto scno_in_r7;
-	/* ARM mode */
-	/* Check EABI/OABI by examining SVC insn's low 24 bits */
-	errno = 0;
-	scno = ptrace(PTRACE_PEEKTEXT, tcp->pid, (void *)(arm_regs.ARM_pc - 4), NULL);
-	if (errno)
-		return -1;
-	/* EABI syscall convention? */
-	if ((unsigned long) scno != 0xef000000) {
-		/* No, it's OABI */
-		if ((scno & 0x0ff00000) != 0x0f900000) {
-			fprintf(stderr, "pid %d unknown syscall trap 0x%08lx\n",
-				tcp->pid, scno);
-			return -1;
-		}
-		/* Fixup the syscall number */
-		scno &= 0x000fffff;
-	} else {
- scno_in_r7:
-		scno = arm_regs.ARM_r7;
-	}
-# else /* __ARM_EABI__ || !ENABLE_ARM_OABI */
-	scno = arm_regs.ARM_r7;
-# endif
-	scno = shuffle_scno(scno);
-#elif defined(M68K)
-	if (upeek(tcp->pid, 4*PT_ORIG_D0, &scno) < 0)
-		return -1;
-#elif defined(MIPS)
-	scno = mips_REG_V0;
-
-	if (!SCNO_IN_RANGE(scno)) {
-		if (mips_REG_A3 == 0 || mips_REG_A3 == (uint64_t) -1) {
-			if (debug_flag)
-				fprintf(stderr, "stray syscall exit: v0 = %ld\n", scno);
-			return 0;
-		}
-	}
-#elif defined(ALPHA)
-	if (upeek(tcp->pid, REG_A3, &alpha_a3) < 0)
-		return -1;
-	if (upeek(tcp->pid, REG_R0, &scno) < 0)
-		return -1;
-
-	/*
-	 * Do some sanity checks to figure out if it's
-	 * really a syscall entry
-	 */
-	if (!SCNO_IN_RANGE(scno)) {
-		if (alpha_a3 == 0 || alpha_a3 == -1) {
-			if (debug_flag)
-				fprintf(stderr, "stray syscall exit: r0 = %ld\n", scno);
-			return 0;
-		}
-	}
-#elif defined(SPARC) || defined(SPARC64)
-	/* Disassemble the syscall trap. */
-	/* Retrieve the syscall trap instruction. */
-	unsigned long trap;
-	errno = 0;
-# if defined(SPARC64)
-	trap = ptrace(PTRACE_PEEKTEXT, tcp->pid, (char *)sparc_regs.tpc, 0);
-	trap >>= 32;
-# else
-	trap = ptrace(PTRACE_PEEKTEXT, tcp->pid, (char *)sparc_regs.pc, 0);
-# endif
-	if (errno)
-		return -1;
-
-	/* Disassemble the trap to see what personality to use. */
-	switch (trap) {
-	case 0x91d02010:
-		/* Linux/SPARC syscall trap. */
-		update_personality(tcp, 0);
-		break;
-	case 0x91d0206d:
-		/* Linux/SPARC64 syscall trap. */
-		update_personality(tcp, 2);
-		break;
-	case 0x91d02000:
-		/* SunOS syscall trap. (pers 1) */
-		fprintf(stderr, "syscall: SunOS no support\n");
-		return -1;
-	case 0x91d02008:
-		/* Solaris 2.x syscall trap. (per 2) */
-		update_personality(tcp, 1);
-		break;
-	case 0x91d02009:
-		/* NetBSD/FreeBSD syscall trap. */
-		fprintf(stderr, "syscall: NetBSD/FreeBSD not supported\n");
-		return -1;
-	case 0x91d02027:
-		/* Solaris 2.x gettimeofday */
-		update_personality(tcp, 1);
-		break;
-	default:
-# if defined(SPARC64)
-		fprintf(stderr, "syscall: unknown syscall trap %08lx %016lx\n", trap, sparc_regs.tpc);
-# else
-		fprintf(stderr, "syscall: unknown syscall trap %08lx %08lx\n", trap, sparc_regs.pc);
-# endif
-		return -1;
-	}
-
-	/* Extract the system call number from the registers. */
-	if (trap == 0x91d02027)
-		scno = 156;
-	else
-		scno = sparc_regs.u_regs[U_REG_G1];
-	if (scno == 0) {
-		scno = sparc_regs.u_regs[U_REG_O0];
-		memmove(&sparc_regs.u_regs[U_REG_O0], &sparc_regs.u_regs[U_REG_O1], 7*sizeof(sparc_regs.u_regs[0]));
-	}
-#elif defined(HPPA)
-	if (upeek(tcp->pid, PT_GR20, &scno) < 0)
-		return -1;
-#elif defined(SH)
-	/*
-	 * In the new syscall ABI, the system call number is in R3.
-	 */
-	if (upeek(tcp->pid, 4*(REG_REG0+3), &scno) < 0)
-		return -1;
-
-	if (scno < 0) {
-		/* Odd as it may seem, a glibc bug has been known to cause
-		   glibc to issue bogus negative syscall numbers.  So for
-		   our purposes, make strace print what it *should* have been */
-		long correct_scno = (scno & 0xff);
-		if (debug_flag)
-			fprintf(stderr,
-				"Detected glibc bug: bogus system call"
-				" number = %ld, correcting to %ld\n",
-				scno,
-				correct_scno);
-		scno = correct_scno;
-	}
-#elif defined(SH64)
-	if (upeek(tcp->pid, REG_SYSCALL, &scno) < 0)
-		return -1;
-	scno &= 0xFFFF;
-#elif defined(CRISV10) || defined(CRISV32)
-	if (upeek(tcp->pid, 4*PT_R9, &scno) < 0)
-		return -1;
-#elif defined(TILE)
-	unsigned int currpers;
-	scno = tile_regs.regs[10];
-# ifdef __tilepro__
-	currpers = 1;
-# else
-#  ifndef PT_FLAGS_COMPAT
-#   define PT_FLAGS_COMPAT 0x10000  /* from Linux 3.8 on */
-#  endif
-	if (tile_regs.flags & PT_FLAGS_COMPAT)
-		currpers = 1;
-	else
-		currpers = 0;
-# endif
-	update_personality(tcp, currpers);
-#elif defined(MICROBLAZE)
-	if (upeek(tcp->pid, 0, &scno) < 0)
-		return -1;
-#elif defined(OR1K)
-	scno = or1k_regs.gpr[11];
-#elif defined(METAG)
-	scno = metag_regs.dx[0][1];	/* syscall number in D1Re0 (D1.0) */
-#elif defined(XTENSA)
-	if (upeek(tcp->pid, SYSCALL_NR, &scno) < 0)
-		return -1;
-# elif defined(ARC)
-	scno = arc_regs.scratch.r8;
-#endif
-
-	tcp->scno = scno;
-	if (SCNO_IS_VALID(tcp->scno)) {
-		tcp->s_ent = &sysent[scno];
-		tcp->qual_flg = qual_flags[scno];
-	} else {
-		static const struct_sysent unknown = {
-			.nargs = MAX_ARGS,
-			.sys_flags = 0,
-			.sys_func = printargs,
-			.sys_name = "unknown", /* not used */
-		};
-		tcp->s_ent = &unknown;
-		tcp->qual_flg = UNDEFINED_SCNO | QUAL_RAW | DEFAULT_QUAL_FLAGS;
-	}
-	return 1;
-}
-
-/*
- * Cannot rely on __kernel_[u]long_t being defined,
- * it is quite a recent feature of <asm/posix_types.h>.
- */
-#ifdef __kernel_long_t
-typedef __kernel_long_t kernel_long_t;
-typedef __kernel_ulong_t kernel_ulong_t;
-#else
-# ifdef X32
-typedef long long kernel_long_t;
-typedef unsigned long long kernel_ulong_t;
-# else
-typedef long kernel_long_t;
-typedef unsigned long kernel_ulong_t;
-# endif
-#endif
-
-/*
- * Check the syscall return value register value for whether it is
- * a negated errno code indicating an error, or a success return value.
- */
-static inline bool
-is_negated_errno(kernel_ulong_t val)
-{
-	/* Linux kernel defines MAX_ERRNO to 4095. */
-	kernel_ulong_t max = -(kernel_long_t) 4095;
-
-#if SUPPORTED_PERSONALITIES > 1 && SIZEOF_LONG > 4
-	if (current_wordsize < sizeof(val)) {
-		val = (uint32_t) val;
-		max = (uint32_t) max;
-	}
-#elif defined X32
-	/*
-	 * current_wordsize is 4 even in personality 0 (native X32)
-	 * but truncation _must not_ be done in it.
-	 * can't check current_wordsize here!
-	 */
-	if (current_personality != 0) {
-		val = (uint32_t) val;
-		max = (uint32_t) max;
-	}
-#endif
-
-	return val >= max;
-}
-
-/* Return -1 on error or 1 on success (never 0!) */
-static int
-get_syscall_args(struct tcb *tcp)
-{
-	int i, nargs;
-
-	nargs = tcp->s_ent->nargs;
-
-#if defined(S390) || defined(S390X)
-	(void)i;
-	(void)nargs;
-	tcp->u_arg[0] = s390_regset.orig_gpr2;
-	tcp->u_arg[1] = s390_regset.gprs[3];
-	tcp->u_arg[2] = s390_regset.gprs[4];
-	tcp->u_arg[3] = s390_regset.gprs[5];
-	tcp->u_arg[4] = s390_regset.gprs[6];
-	tcp->u_arg[5] = s390_regset.gprs[7];
-#elif defined(ALPHA)
-	for (i = 0; i < nargs; ++i)
-		if (upeek(tcp->pid, REG_A0+i, &tcp->u_arg[i]) < 0)
-			return -1;
-#elif defined(IA64)
-	if (!ia64_ia32mode) {
-		unsigned long *rbs_end =
-			(unsigned long *) ia64_regs.ar[PT_AUR_BSP];
-		unsigned long sof = (ia64_regs.cfm >> 0) & 0x7f;
-		unsigned long sol = (ia64_regs.cfm >> 7) & 0x7f;
-		unsigned long *out0 = ia64_rse_skip_regs(rbs_end, -sof + sol);
-
-		for (i = 0; i < nargs; ++i) {
-			if (umoven(tcp, (unsigned long) ia64_rse_skip_regs(out0, i),
-				   sizeof(long), (char *) &tcp->u_arg[i]) < 0)
-				return -1;
-		}
-	} else {
-		(void)i;
-		(void)nargs;
-		/* truncate away IVE sign-extension */
-		tcp->u_arg[0] = 0xffffffff & ia64_regs.gr[11]; /* EBX */
-		tcp->u_arg[1] = 0xffffffff & ia64_regs.gr[ 9]; /* ECX */
-		tcp->u_arg[2] = 0xffffffff & ia64_regs.gr[10]; /* EDX */
-		tcp->u_arg[3] = 0xffffffff & ia64_regs.gr[14]; /* ESI */
-		tcp->u_arg[4] = 0xffffffff & ia64_regs.gr[15]; /* EDI */
-		tcp->u_arg[5] = 0xffffffff & ia64_regs.gr[13]; /* EBP */
-	}
-#elif defined LINUX_MIPSN64
-	(void)i;
-	(void)nargs;
-	tcp->u_arg[0] = mips_REG_A0;
-	tcp->u_arg[1] = mips_REG_A1;
-	tcp->u_arg[2] = mips_REG_A2;
-	tcp->u_arg[3] = mips_REG_A3;
-	tcp->u_arg[4] = mips_REG_A4;
-	tcp->u_arg[5] = mips_REG_A5;
-#elif defined LINUX_MIPSN32
-	(void)i;
-	(void)nargs;
-	tcp->u_arg[0] = tcp->ext_arg[0] = mips_REG_A0;
-	tcp->u_arg[1] = tcp->ext_arg[1] = mips_REG_A1;
-	tcp->u_arg[2] = tcp->ext_arg[2] = mips_REG_A2;
-	tcp->u_arg[3] = tcp->ext_arg[3] = mips_REG_A3;
-	tcp->u_arg[4] = tcp->ext_arg[4] = mips_REG_A4;
-	tcp->u_arg[5] = tcp->ext_arg[5] = mips_REG_A5;
-#elif defined LINUX_MIPSO32
-	(void)i;
-	(void)nargs;
-	tcp->u_arg[0] = mips_REG_A0;
-	tcp->u_arg[1] = mips_REG_A1;
-	tcp->u_arg[2] = mips_REG_A2;
-	tcp->u_arg[3] = mips_REG_A3;
-	if (nargs > 4) {
-		umoven(tcp, mips_REG_SP + 4 * 4,
-		       (nargs - 4) * sizeof(tcp->u_arg[0]),
-		       (char *)(tcp->u_arg + 4));
-	}
-#elif defined(POWERPC)
-	(void)i;
-	(void)nargs;
-	tcp->u_arg[0] = ppc_regs.orig_gpr3;
-	tcp->u_arg[1] = ppc_regs.gpr[4];
-	tcp->u_arg[2] = ppc_regs.gpr[5];
-	tcp->u_arg[3] = ppc_regs.gpr[6];
-	tcp->u_arg[4] = ppc_regs.gpr[7];
-	tcp->u_arg[5] = ppc_regs.gpr[8];
-#elif defined(SPARC) || defined(SPARC64)
-	for (i = 0; i < nargs; ++i)
-		tcp->u_arg[i] = sparc_regs.u_regs[U_REG_O0 + i];
-#elif defined(HPPA)
-	for (i = 0; i < nargs; ++i)
-		if (upeek(tcp->pid, PT_GR26-4*i, &tcp->u_arg[i]) < 0)
-			return -1;
-#elif defined(ARM) || defined(AARCH64)
-# if defined(AARCH64)
-	if (tcp->currpers == 1)
-		for (i = 0; i < nargs; ++i)
-			tcp->u_arg[i] = aarch64_regs.regs[i];
-	else
-# endif
-	for (i = 0; i < nargs; ++i)
-		tcp->u_arg[i] = arm_regs.uregs[i];
-#elif defined(AVR32)
-	(void)i;
-	(void)nargs;
-	tcp->u_arg[0] = avr32_regs.r12;
-	tcp->u_arg[1] = avr32_regs.r11;
-	tcp->u_arg[2] = avr32_regs.r10;
-	tcp->u_arg[3] = avr32_regs.r9;
-	tcp->u_arg[4] = avr32_regs.r5;
-	tcp->u_arg[5] = avr32_regs.r3;
-#elif defined(BFIN)
-	static const int argreg[MAX_ARGS] = { PT_R0, PT_R1, PT_R2, PT_R3, PT_R4, PT_R5 };
-
-	for (i = 0; i < nargs; ++i)
-		if (upeek(tcp->pid, argreg[i], &tcp->u_arg[i]) < 0)
-			return -1;
-#elif defined(SH)
-	static const int syscall_regs[MAX_ARGS] = {
-		4 * (REG_REG0+4), 4 * (REG_REG0+5), 4 * (REG_REG0+6),
-		4 * (REG_REG0+7), 4 * (REG_REG0  ), 4 * (REG_REG0+1)
-	};
-
-	for (i = 0; i < nargs; ++i)
-		if (upeek(tcp->pid, syscall_regs[i], &tcp->u_arg[i]) < 0)
-			return -1;
-#elif defined(SH64)
-	int i;
-	/* Registers used by SH5 Linux system calls for parameters */
-	static const int syscall_regs[MAX_ARGS] = { 2, 3, 4, 5, 6, 7 };
-
-	for (i = 0; i < nargs; ++i)
-		if (upeek(tcp->pid, REG_GENERAL(syscall_regs[i]), &tcp->u_arg[i]) < 0)
-			return -1;
-#elif defined(I386)
-	(void)i;
-	(void)nargs;
-	tcp->u_arg[0] = i386_regs.ebx;
-	tcp->u_arg[1] = i386_regs.ecx;
-	tcp->u_arg[2] = i386_regs.edx;
-	tcp->u_arg[3] = i386_regs.esi;
-	tcp->u_arg[4] = i386_regs.edi;
-	tcp->u_arg[5] = i386_regs.ebp;
-#elif defined(X86_64) || defined(X32)
-	(void)i;
-	(void)nargs;
-	if (x86_io.iov_len != sizeof(i386_regs)) {
-		/* x86-64 or x32 ABI */
-		tcp->u_arg[0] = x86_64_regs.rdi;
-		tcp->u_arg[1] = x86_64_regs.rsi;
-		tcp->u_arg[2] = x86_64_regs.rdx;
-		tcp->u_arg[3] = x86_64_regs.r10;
-		tcp->u_arg[4] = x86_64_regs.r8;
-		tcp->u_arg[5] = x86_64_regs.r9;
-#  ifdef X32
-		tcp->ext_arg[0] = x86_64_regs.rdi;
-		tcp->ext_arg[1] = x86_64_regs.rsi;
-		tcp->ext_arg[2] = x86_64_regs.rdx;
-		tcp->ext_arg[3] = x86_64_regs.r10;
-		tcp->ext_arg[4] = x86_64_regs.r8;
-		tcp->ext_arg[5] = x86_64_regs.r9;
-#  endif
-	} else {
-		/* i386 ABI */
-		/* Zero-extend from 32 bits */
-		/* Use widen_to_long(tcp->u_arg[N]) in syscall handlers
-		 * if you need to use *sign-extended* parameter.
-		 */
-		tcp->u_arg[0] = (long)(uint32_t)i386_regs.ebx;
-		tcp->u_arg[1] = (long)(uint32_t)i386_regs.ecx;
-		tcp->u_arg[2] = (long)(uint32_t)i386_regs.edx;
-		tcp->u_arg[3] = (long)(uint32_t)i386_regs.esi;
-		tcp->u_arg[4] = (long)(uint32_t)i386_regs.edi;
-		tcp->u_arg[5] = (long)(uint32_t)i386_regs.ebp;
-	}
-#elif defined(MICROBLAZE)
-	for (i = 0; i < nargs; ++i)
-		if (upeek(tcp->pid, (5 + i) * 4, &tcp->u_arg[i]) < 0)
-			return -1;
-#elif defined(CRISV10) || defined(CRISV32)
-	static const int crisregs[MAX_ARGS] = {
-		4*PT_ORIG_R10, 4*PT_R11, 4*PT_R12,
-		4*PT_R13     , 4*PT_MOF, 4*PT_SRP
-	};
-
-	for (i = 0; i < nargs; ++i)
-		if (upeek(tcp->pid, crisregs[i], &tcp->u_arg[i]) < 0)
-			return -1;
-#elif defined(TILE)
-	for (i = 0; i < nargs; ++i)
-		tcp->u_arg[i] = tile_regs.regs[i];
-#elif defined(M68K)
-	for (i = 0; i < nargs; ++i)
-		if (upeek(tcp->pid, (i < 5 ? i : i + 2)*4, &tcp->u_arg[i]) < 0)
-			return -1;
-#elif defined(OR1K)
-	(void)nargs;
-	for (i = 0; i < 6; ++i)
-		tcp->u_arg[i] = or1k_regs.gpr[3 + i];
-#elif defined(METAG)
-	for (i = 0; i < nargs; i++)
-		/* arguments go backwards from D1Ar1 (D1.3) */
-		tcp->u_arg[i] = ((unsigned long *)&metag_regs.dx[3][1])[-i];
-#elif defined(XTENSA)
-	/* arg0: a6, arg1: a3, arg2: a4, arg3: a5, arg4: a8, arg5: a9 */
-	static const int xtensaregs[MAX_ARGS] = { 6, 3, 4, 5, 8, 9 };
-	for (i = 0; i < nargs; ++i)
-		if (upeek(tcp->pid, REG_A_BASE + xtensaregs[i], &tcp->u_arg[i]) < 0)
-			return -1;
-# elif defined(ARC)
-	long *arc_args = &arc_regs.scratch.r0;
-	for (i = 0; i < nargs; ++i)
-		tcp->u_arg[i] = *arc_args--;
-
-#else /* Other architecture (32bits specific) */
-	for (i = 0; i < nargs; ++i)
-		if (upeek(tcp->pid, i*4, &tcp->u_arg[i]) < 0)
-			return -1;
-#endif
-	return 1;
-}
+static int get_syscall_args(struct tcb *);
+static int get_syscall_result(struct tcb *);
 
 static int
 trace_syscall_entering(struct tcb *tcp)
 {
 	int res, scno_good;
 
-	scno_good = res = (get_regs_error ? -1 : get_scno(tcp));
+	scno_good = res = get_scno(tcp);
 	if (res == 0)
 		return res;
 	if (res == 1)
@@ -1840,350 +836,6 @@
 	return res;
 }
 
-/* Returns:
- * 1: ok, continue in trace_syscall_exiting().
- * -1: error, trace_syscall_exiting() should print error indicator
- *    ("????" etc) and bail out.
- */
-static int
-get_syscall_result(struct tcb *tcp)
-{
-#if defined ARCH_REGS_FOR_GETREGSET || defined ARCH_REGS_FOR_GETREGS
-	/* already done by get_regs */
-#elif defined(BFIN)
-	if (upeek(tcp->pid, PT_R0, &bfin_r0) < 0)
-		return -1;
-#elif defined(M68K)
-	if (upeek(tcp->pid, 4*PT_D0, &m68k_d0) < 0)
-		return -1;
-#elif defined(ALPHA)
-	if (upeek(tcp->pid, REG_A3, &alpha_a3) < 0)
-		return -1;
-	if (upeek(tcp->pid, REG_R0, &alpha_r0) < 0)
-		return -1;
-#elif defined(HPPA)
-	if (upeek(tcp->pid, PT_GR28, &hppa_r28) < 0)
-		return -1;
-#elif defined(SH)
-	/* new syscall ABI returns result in R0 */
-	if (upeek(tcp->pid, 4*REG_REG0, (long *)&sh_r0) < 0)
-		return -1;
-#elif defined(SH64)
-	/* ABI defines result returned in r9 */
-	if (upeek(tcp->pid, REG_GENERAL(9), (long *)&sh64_r9) < 0)
-		return -1;
-#elif defined(CRISV10) || defined(CRISV32)
-	if (upeek(tcp->pid, 4*PT_R10, &cris_r10) < 0)
-		return -1;
-#elif defined(MICROBLAZE)
-	if (upeek(tcp->pid, 3 * 4, &microblaze_r3) < 0)
-		return -1;
-#elif defined(XTENSA)
-	if (upeek(tcp->pid, REG_A_BASE + 2, &xtensa_a2) < 0)
-		return -1;
-#else
-# error get_syscall_result is not implemented for this architecture
-#endif
-	return 1;
-}
-
-/* Returns:
- * 1: ok, continue in trace_syscall_exiting().
- * -1: error, trace_syscall_exiting() should print error indicator
- *    ("????" etc) and bail out.
- */
-static void
-get_error(struct tcb *tcp)
-{
-	int u_error = 0;
-	int check_errno = 1;
-	if (tcp->s_ent->sys_flags & SYSCALL_NEVER_FAILS) {
-		check_errno = 0;
-	}
-#if defined(S390) || defined(S390X)
-	if (check_errno && is_negated_errno(s390_regset.gprs[2])) {
-		tcp->u_rval = -1;
-		u_error = -s390_regset.gprs[2];
-	}
-	else {
-		tcp->u_rval = s390_regset.gprs[2];
-	}
-#elif defined(I386)
-	if (check_errno && is_negated_errno(i386_regs.eax)) {
-		tcp->u_rval = -1;
-		u_error = -i386_regs.eax;
-	}
-	else {
-		tcp->u_rval = i386_regs.eax;
-	}
-#elif defined(X86_64) || defined(X32)
-	/*
-	 * In X32, return value is 64-bit (llseek uses one).
-	 * Using merely "long rax" would not work.
-	 */
-	kernel_long_t rax;
-
-	if (x86_io.iov_len == sizeof(i386_regs)) {
-		/* Sign extend from 32 bits */
-		rax = (int32_t) i386_regs.eax;
-	} else {
-		rax = x86_64_regs.rax;
-	}
-	if (check_errno && is_negated_errno(rax)) {
-		tcp->u_rval = -1;
-		u_error = -rax;
-	}
-	else {
-		tcp->u_rval = rax;
-# ifdef X32
-		/* tcp->u_rval contains a truncated value */
-		tcp->u_lrval = rax;
-# endif
-	}
-#elif defined(IA64)
-	if (ia64_ia32mode) {
-		int err = ia64_regs.gr[8];
-		if (check_errno && is_negated_errno(err)) {
-			tcp->u_rval = -1;
-			u_error = -err;
-		}
-		else {
-			tcp->u_rval = err;
-		}
-	} else {
-		if (check_errno && ia64_regs.gr[10]) {
-			tcp->u_rval = -1;
-			u_error = ia64_regs.gr[8];
-		} else {
-			tcp->u_rval = ia64_regs.gr[8];
-		}
-	}
-#elif defined(MIPS)
-	if (check_errno && mips_REG_A3) {
-		tcp->u_rval = -1;
-		u_error = mips_REG_V0;
-	} else {
-# if defined LINUX_MIPSN32
-		tcp->u_lrval = mips_REG_V0;
-# endif
-		tcp->u_rval = mips_REG_V0;
-	}
-#elif defined(POWERPC)
-	if (check_errno && (ppc_regs.ccr & 0x10000000)) {
-		tcp->u_rval = -1;
-		u_error = ppc_regs.gpr[3];
-	}
-	else {
-		tcp->u_rval = ppc_regs.gpr[3];
-	}
-#elif defined(M68K)
-	if (check_errno && is_negated_errno(m68k_d0)) {
-		tcp->u_rval = -1;
-		u_error = -m68k_d0;
-	}
-	else {
-		tcp->u_rval = m68k_d0;
-	}
-#elif defined(ARM) || defined(AARCH64)
-# if defined(AARCH64)
-	if (tcp->currpers == 1) {
-		if (check_errno && is_negated_errno(aarch64_regs.regs[0])) {
-			tcp->u_rval = -1;
-			u_error = -aarch64_regs.regs[0];
-		}
-		else {
-			tcp->u_rval = aarch64_regs.regs[0];
-		}
-	}
-	else
-# endif
-	{
-		if (check_errno && is_negated_errno(arm_regs.ARM_r0)) {
-			tcp->u_rval = -1;
-			u_error = -arm_regs.ARM_r0;
-		}
-		else {
-			tcp->u_rval = arm_regs.ARM_r0;
-		}
-	}
-#elif defined(AVR32)
-	if (check_errno && avr32_regs.r12 && (unsigned) -avr32_regs.r12 < nerrnos) {
-		tcp->u_rval = -1;
-		u_error = -avr32_regs.r12;
-	}
-	else {
-		tcp->u_rval = avr32_regs.r12;
-	}
-#elif defined(BFIN)
-	if (check_errno && is_negated_errno(bfin_r0)) {
-		tcp->u_rval = -1;
-		u_error = -bfin_r0;
-	} else {
-		tcp->u_rval = bfin_r0;
-	}
-#elif defined(ALPHA)
-	if (check_errno && alpha_a3) {
-		tcp->u_rval = -1;
-		u_error = alpha_r0;
-	}
-	else {
-		tcp->u_rval = alpha_r0;
-	}
-#elif defined(SPARC)
-	if (check_errno && sparc_regs.psr & PSR_C) {
-		tcp->u_rval = -1;
-		u_error = sparc_regs.u_regs[U_REG_O0];
-	}
-	else {
-		tcp->u_rval = sparc_regs.u_regs[U_REG_O0];
-	}
-#elif defined(SPARC64)
-	if (check_errno && sparc_regs.tstate & 0x1100000000UL) {
-		tcp->u_rval = -1;
-		u_error = sparc_regs.u_regs[U_REG_O0];
-	}
-	else {
-		tcp->u_rval = sparc_regs.u_regs[U_REG_O0];
-	}
-#elif defined(HPPA)
-	if (check_errno && is_negated_errno(hppa_r28)) {
-		tcp->u_rval = -1;
-		u_error = -hppa_r28;
-	}
-	else {
-		tcp->u_rval = hppa_r28;
-	}
-#elif defined(SH)
-	if (check_errno && is_negated_errno(sh_r0)) {
-		tcp->u_rval = -1;
-		u_error = -sh_r0;
-	}
-	else {
-		tcp->u_rval = sh_r0;
-	}
-#elif defined(SH64)
-	if (check_errno && is_negated_errno(sh64_r9)) {
-		tcp->u_rval = -1;
-		u_error = -sh64_r9;
-	}
-	else {
-		tcp->u_rval = sh64_r9;
-	}
-#elif defined(METAG)
-	/* result pointer in D0Re0 (D0.0) */
-	if (check_errno && is_negated_errno(metag_regs.dx[0][0])) {
-		tcp->u_rval = -1;
-		u_error = -metag_regs.dx[0][0];
-	}
-	else {
-		tcp->u_rval = metag_regs.dx[0][0];
-	}
-#elif defined(CRISV10) || defined(CRISV32)
-	if (check_errno && cris_r10 && (unsigned) -cris_r10 < nerrnos) {
-		tcp->u_rval = -1;
-		u_error = -cris_r10;
-	}
-	else {
-		tcp->u_rval = cris_r10;
-	}
-#elif defined(TILE)
-	/*
-	 * The standard tile calling convention returns the value (or negative
-	 * errno) in r0, and zero (or positive errno) in r1.
-	 * Until at least kernel 3.8, however, the r1 value is not reflected
-	 * in ptregs at this point, so we use r0 here.
-	 */
-	if (check_errno && is_negated_errno(tile_regs.regs[0])) {
-		tcp->u_rval = -1;
-		u_error = -tile_regs.regs[0];
-	} else {
-		tcp->u_rval = tile_regs.regs[0];
-	}
-#elif defined(MICROBLAZE)
-	if (check_errno && is_negated_errno(microblaze_r3)) {
-		tcp->u_rval = -1;
-		u_error = -microblaze_r3;
-	}
-	else {
-		tcp->u_rval = microblaze_r3;
-	}
-#elif defined(OR1K)
-	if (check_errno && is_negated_errno(or1k_regs.gpr[11])) {
-		tcp->u_rval = -1;
-		u_error = -or1k_regs.gpr[11];
-	}
-	else {
-		tcp->u_rval = or1k_regs.gpr[11];
-	}
-#elif defined(XTENSA)
-	if (check_errno && is_negated_errno(xtensa_a2)) {
-		tcp->u_rval = -1;
-		u_error = -xtensa_a2;
-	}
-	else {
-		tcp->u_rval = xtensa_a2;
-	}
-#elif defined(ARC)
-	if (check_errno && is_negated_errno(arc_regs.scratch.r0)) {
-		tcp->u_rval = -1;
-		u_error = -arc_regs.scratch.r0;
-	}
-	else {
-		tcp->u_rval = arc_regs.scratch.r0;
-	}
-#endif
-	tcp->u_error = u_error;
-}
-
-static void
-dumpio(struct tcb *tcp)
-{
-	int (*func)();
-
-	if (syserror(tcp))
-		return;
-	if ((unsigned long) tcp->u_arg[0] >= num_quals)
-		return;
-	func = tcp->s_ent->sys_func;
-	if (func == printargs)
-		return;
-	if (qual_flags[tcp->u_arg[0]] & QUAL_READ) {
-		if (func == sys_read ||
-		    func == sys_pread ||
-		    func == sys_recv ||
-		    func == sys_recvfrom) {
-			dumpstr(tcp, tcp->u_arg[1], tcp->u_rval);
-			return;
-		} else if (func == sys_readv) {
-			dumpiov(tcp, tcp->u_arg[2], tcp->u_arg[1]);
-			return;
-#if HAVE_SENDMSG
-		} else if (func == sys_recvmsg) {
-			dumpiov_in_msghdr(tcp, tcp->u_arg[1]);
-			return;
-		} else if (func == sys_recvmmsg) {
-			dumpiov_in_mmsghdr(tcp, tcp->u_arg[1]);
-			return;
-#endif
-		}
-	}
-	if (qual_flags[tcp->u_arg[0]] & QUAL_WRITE) {
-		if (func == sys_write ||
-		    func == sys_pwrite ||
-		    func == sys_send ||
-		    func == sys_sendto)
-			dumpstr(tcp, tcp->u_arg[1], tcp->u_arg[2]);
-		else if (func == sys_writev)
-			dumpiov(tcp, tcp->u_arg[2], tcp->u_arg[1]);
-#if HAVE_SENDMSG
-		else if (func == sys_sendmsg)
-			dumpiov_in_msghdr(tcp, tcp->u_arg[1]);
-		else if (func == sys_sendmmsg)
-			dumpiov_in_mmsghdr(tcp, tcp->u_arg[1]);
-#endif
-	}
-}
-
 static int
 trace_syscall_exiting(struct tcb *tcp)
 {
@@ -2208,7 +860,6 @@
 #endif
 	res = (get_regs_error ? -1 : get_syscall_result(tcp));
 	if (res == 1) {
-		get_error(tcp); /* never fails */
 		if (filtered(tcp) || hide_log_until_execve)
 			goto ret;
 	}
@@ -2239,6 +890,7 @@
 	}
 	printing_tcp = tcp;
 
+	tcp->s_prev_ent = NULL;
 	if (res != 1) {
 		/* There was error in one of prior ptrace ops */
 		tprints(") ");
@@ -2248,6 +900,7 @@
 		tcp->flags &= ~TCB_INSYSCALL;
 		return res;
 	}
+	tcp->s_prev_ent = tcp->s_ent;
 
 	sys_res = 0;
 	if (tcp->qual_flg & QUAL_RAW) {
@@ -2426,3 +1079,232 @@
 	return exiting(tcp) ?
 		trace_syscall_exiting(tcp) : trace_syscall_entering(tcp);
 }
+
+/*
+ * Cannot rely on __kernel_[u]long_t being defined,
+ * it is quite a recent feature of <asm/posix_types.h>.
+ */
+#ifdef __kernel_long_t
+typedef __kernel_long_t kernel_long_t;
+typedef __kernel_ulong_t kernel_ulong_t;
+#else
+# ifdef X32
+typedef long long kernel_long_t;
+typedef unsigned long long kernel_ulong_t;
+# else
+typedef long kernel_long_t;
+typedef unsigned long kernel_ulong_t;
+# endif
+#endif
+
+/*
+ * Check the syscall return value register value for whether it is
+ * a negated errno code indicating an error, or a success return value.
+ */
+static inline bool
+is_negated_errno(kernel_ulong_t val)
+{
+	/* Linux kernel defines MAX_ERRNO to 4095. */
+	kernel_ulong_t max = -(kernel_long_t) 4095;
+
+#if SUPPORTED_PERSONALITIES > 1 && SIZEOF_LONG > 4
+	if (current_wordsize < sizeof(val)) {
+		val = (uint32_t) val;
+		max = (uint32_t) max;
+	}
+#elif defined X32
+	/*
+	 * current_wordsize is 4 even in personality 0 (native X32)
+	 * but truncation _must not_ be done in it.
+	 * can't check current_wordsize here!
+	 */
+	if (current_personality != 0) {
+		val = (uint32_t) val;
+		max = (uint32_t) max;
+	}
+#endif
+
+	return val >= max;
+}
+
+#include "arch_regs.c"
+
+#ifdef HAVE_GETRVAL2
+# include "arch_getrval2.c"
+#endif
+
+void
+print_pc(struct tcb *tcp)
+{
+	const char *fmt;
+	const char *bad;
+
+#ifdef current_wordsize
+# define pc_wordsize current_wordsize
+#else
+# define pc_wordsize personality_wordsize[tcp->currpers]
+#endif
+
+	if (pc_wordsize == 4) {
+		fmt = "[%08lx] ";
+		bad = "[????????] ";
+	} else {
+		fmt = "[%016lx] ";
+		bad = "[????????????????] ";
+	}
+
+#undef pc_wordsize
+#define PRINTBADPC tprints(bad)
+
+	if (get_regs_error) {
+		PRINTBADPC;
+		return;
+	}
+
+#include "print_pc.c"
+}
+
+#if defined X86_64 || defined POWERPC
+# include "getregs_old.c"
+#endif
+
+#if defined ARCH_REGS_FOR_GETREGSET
+static long
+get_regset(pid_t pid)
+{
+# ifdef ARCH_IOVEC_FOR_GETREGSET
+	/* variable iovec */
+	ARCH_IOVEC_FOR_GETREGSET.iov_len = sizeof(ARCH_REGS_FOR_GETREGSET);
+	return ptrace(PTRACE_GETREGSET, pid, NT_PRSTATUS,
+		      &ARCH_IOVEC_FOR_GETREGSET);
+# else
+	/* constant iovec */
+	static struct iovec io = {
+		.iov_base = &ARCH_REGS_FOR_GETREGSET,
+		.iov_len = sizeof(ARCH_REGS_FOR_GETREGSET)
+	};
+	return ptrace(PTRACE_GETREGSET, pid, NT_PRSTATUS, &io);
+
+# endif
+}
+#endif /* ARCH_REGS_FOR_GETREGSET */
+
+void
+get_regs(pid_t pid)
+{
+#ifdef ARCH_REGS_FOR_GETREGSET
+# ifdef X86_64
+	/* Try PTRACE_GETREGSET first, fallback to PTRACE_GETREGS. */
+	static int getregset_support;
+
+	if (getregset_support >= 0) {
+		get_regs_error = get_regset(pid);
+		if (getregset_support > 0)
+			return;
+		if (get_regs_error >= 0) {
+			getregset_support = 1;
+			return;
+		}
+		if (errno == EPERM || errno == ESRCH)
+			return;
+		getregset_support = -1;
+	}
+	getregs_old(pid);
+# else /* !X86_64 */
+	/* Assume that PTRACE_GETREGSET works. */
+	get_regs_error = get_regset(pid);
+# endif
+#elif defined ARCH_REGS_FOR_GETREGS
+# if defined SPARC || defined SPARC64
+	/* SPARC systems have the meaning of data and addr reversed */
+	get_regs_error = ptrace(PTRACE_GETREGS, pid, (char *)&ARCH_REGS_FOR_GETREGS, 0);
+# elif defined POWERPC
+	static bool old_kernel = 0;
+	if (old_kernel)
+		goto old;
+	get_regs_error = ptrace(PTRACE_GETREGS, pid, NULL, &ARCH_REGS_FOR_GETREGS);
+	if (get_regs_error && errno == EIO) {
+		old_kernel = 1;
+ old:
+		get_regs_error = getregs_old(pid);
+	}
+# else
+	/* Assume that PTRACE_GETREGS works. */
+	get_regs_error = ptrace(PTRACE_GETREGS, pid, NULL, &ARCH_REGS_FOR_GETREGS);
+# endif
+
+#else /* !ARCH_REGS_FOR_GETREGSET && !ARCH_REGS_FOR_GETREGS */
+#  warning get_regs is not implemented for this architecture yet
+	get_regs_error = 0;
+#endif
+}
+
+/* Returns:
+ * 0: "ignore this ptrace stop", bail out of trace_syscall_entering() silently.
+ * 1: ok, continue in trace_syscall_entering().
+ * other: error, trace_syscall_entering() should print error indicator
+ *    ("????" etc) and bail out.
+ */
+int
+get_scno(struct tcb *tcp)
+{
+	if (get_regs_error)
+		return -1;
+
+	long scno = 0;
+
+#include "get_scno.c"
+
+	tcp->scno = scno;
+	if (SCNO_IS_VALID(tcp->scno)) {
+		tcp->s_ent = &sysent[scno];
+		tcp->qual_flg = qual_flags[scno];
+	} else {
+		static const struct_sysent unknown = {
+			.nargs = MAX_ARGS,
+			.sys_flags = 0,
+			.sys_func = printargs,
+			.sys_name = "unknown", /* not used */
+		};
+		tcp->s_ent = &unknown;
+		tcp->qual_flg = UNDEFINED_SCNO | QUAL_RAW | DEFAULT_QUAL_FLAGS;
+		if (debug_flag)
+			fprintf(stderr, "pid %d invalid syscall %ld\n",
+				tcp->pid, scno);
+	}
+	return 1;
+}
+
+/* Return -1 on error or 1 on success (never 0!) */
+static int
+get_syscall_args(struct tcb *tcp)
+{
+#include "get_syscall_args.c"
+	return 1;
+}
+
+static void
+get_error(struct tcb *tcp)
+{
+	const bool check_errno = !(tcp->s_ent->sys_flags & SYSCALL_NEVER_FAILS);
+	tcp->u_error = 0;
+
+#include "get_error.c"
+}
+
+/* Returns:
+ * 1: ok, continue in trace_syscall_exiting().
+ * -1: error, trace_syscall_exiting() should print error indicator
+ *    ("????" etc) and bail out.
+ */
+static int
+get_syscall_result(struct tcb *tcp)
+{
+#if defined ARCH_REGS_FOR_GETREGSET || defined ARCH_REGS_FOR_GETREGS
+	/* already done by get_regs */
+#else
+# include "get_syscall_result.c"
+#endif
+	get_error(tcp);
+	return 1;
+}
diff --git a/sysctl.c b/sysctl.c
index 70cc5d9..a550eda 100644
--- a/sysctl.c
+++ b/sysctl.c
@@ -27,7 +27,7 @@
 	size = sizeof(int) * (unsigned long) info.nlen;
 	name = (size / sizeof(int) != (unsigned long) info.nlen) ? NULL : malloc(size);
 	if (name == NULL ||
-	    umoven(tcp, (unsigned long) info.name, size, (char *) name) < 0) {
+	    umoven(tcp, (unsigned long) info.name, size, name) < 0) {
 		free(name);
 		if (entering(tcp))
 			tprintf("{%p, %d, %p, %p, %p, %lu}",
diff --git a/test/.gitignore b/test/.gitignore
new file mode 100644
index 0000000..fba8c9d
--- /dev/null
+++ b/test/.gitignore
@@ -0,0 +1,18 @@
+childthread
+clone
+fork
+leaderkill
+many_looping_threads
+mmap_offset_decode
+mtd
+seccomp
+sfd
+sig
+sigkill_rain
+skodic
+threaded_execve
+ubi
+vfork
+wait_must_be_interruptible
+x32_lseek
+x32_mmap
diff --git a/test/Makefile b/test/Makefile
new file mode 100644
index 0000000..dbc5008
--- /dev/null
+++ b/test/Makefile
@@ -0,0 +1,20 @@
+CFLAGS += -Wall
+
+PROGS = \
+    vfork fork sig skodic clone leaderkill childthread \
+    sigkill_rain wait_must_be_interruptible threaded_execve \
+    mtd ubi seccomp sfd mmap_offset_decode x32_lseek x32_mmap \
+    many_looping_threads
+
+all: $(PROGS)
+
+leaderkill: LDFLAGS += -pthread
+
+childthread: LDFLAGS += -pthread
+
+many_looping_threads: LDFLAGS += -pthread
+
+clean distclean:
+	rm -f *.o core $(PROGS) *.gdb
+
+.PHONY: all clean distclean
diff --git a/test/many_looping_threads.c b/test/many_looping_threads.c
new file mode 100644
index 0000000..918bd9d
--- /dev/null
+++ b/test/many_looping_threads.c
@@ -0,0 +1,49 @@
+// This testcase, when run with large number of threads
+// under stace -f, may never finish because strace does not
+// ensure any fairness in thread scheduling:
+// it restarts threads as they stop. If daughter threads crowd out
+// the "mother" and _they_ get continually restarted by strace,
+// the end of spawning loop will never be reached.
+//
+// Also, it is a testcase which triggers the
+// "strace: Exit of unknown pid 32457 seen"
+// message when on testcase exit, strace sees deaths of newly-attached
+// threads _before_ their first syscall stop.
+//
+#include <stdio.h>
+#include <pthread.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include <signal.h>
+#include <stdlib.h>
+
+static int thd_no;
+
+static void *sub_thd(void *c)
+{
+	dprintf(1, "sub-thread %d created\n", ++thd_no);
+	for (;;)
+		getuid();
+	return NULL;
+}
+
+int main(int argc, char *argv[])
+{
+	int i;
+	pthread_t *thd;
+	int num_threads = 1;
+
+	if (argv[1])
+		num_threads = atoi(argv[1]);
+
+	thd = malloc(num_threads * sizeof(thd[0]));
+	dprintf(1, "test start, num_threads:%d...\n", num_threads);
+
+	for (i = 0; i < num_threads; i++) {
+		pthread_create(&thd[i], NULL, sub_thd, NULL);
+		dprintf(1, "after pthread_create\n");
+	}
+
+	/* Exit. This kills all threads */
+	return 0;
+}
diff --git a/tests/.gitignore b/tests/.gitignore
index 8efb0ef..6903a5c 100644
--- a/tests/.gitignore
+++ b/tests/.gitignore
@@ -6,12 +6,16 @@
 ipc_msg
 ipc_sem
 ipc_shm
+mmap
+mmap64
 mmsg
 net-accept-connect
 netlink_inet_diag
 netlink_unix_diag
 pc
+pipe
 scm_rights
+seccomp
 select
 set_ptracer_any
 sigaction
@@ -24,6 +28,8 @@
 uid16
 uid32
 uio
+umovestr
+umovestr2
 unix-pair-send-recv
 *.log
 *.log.*
diff --git a/tests/Makefile.am b/tests/Makefile.am
index 7f9a11e..e5dae02 100644
--- a/tests/Makefile.am
+++ b/tests/Makefile.am
@@ -15,12 +15,16 @@
 	ipc_msg \
 	ipc_sem \
 	ipc_shm \
+	mmap \
+	mmap64 \
 	mmsg \
 	net-accept-connect \
 	netlink_inet_diag \
 	netlink_unix_diag \
 	pc \
+	pipe \
 	scm_rights \
+	seccomp \
 	select \
 	set_ptracer_any \
 	sigaction \
@@ -33,8 +37,11 @@
 	uid16 \
 	uid32 \
 	uio \
+	umovestr \
+	umovestr2 \
 	unix-pair-send-recv
 
+mmap64_CFLAGS = $(AM_CFLAGS) -D_FILE_OFFSET_BITS=64
 pc_LDADD = $(dl_LIBS)
 stat_CFLAGS = $(AM_CFLAGS) -D_FILE_OFFSET_BITS=64
 statfs_CFLAGS = $(AM_CFLAGS) -D_FILE_OFFSET_BITS=64
@@ -56,6 +63,7 @@
 	ipc_shm.test \
 	ipc_sem.test \
 	scm_rights-fd.test \
+	seccomp.test \
 	select.test \
 	sigaction.test \
 	sigreturn.test \
@@ -63,12 +71,17 @@
 	stat32-v.test \
 	stat64-v.test \
 	statfs.test \
+	mmap.test \
+	mmap64.test \
 	mmsg.test \
 	net.test \
 	net-fd.test \
 	net-yy.test \
+	pipe.test \
 	pc.test \
 	sun_path.test \
+	umovestr.test \
+	umovestr2.test \
 	unix-yy.test \
 	uid.test \
 	uid16.test \
@@ -84,7 +97,7 @@
 
 TEST_LOG_COMPILER = $(srcdir)/run.sh
 
-EXTRA_DIST = init.sh run.sh \
+EXTRA_DIST = init.sh run.sh match.awk \
 	     caps.awk \
 	     dumpio.expected \
 	     fanotify_mark.expected \
@@ -98,12 +111,14 @@
 	     net-fd.expected \
 	     net-yy-accept.awk \
 	     net-yy-connect.awk \
+	     pipe.expected \
 	     select.awk \
 	     sigaction.awk \
 	     statfs.expected \
 	     sun_path.expected \
 	     uid.awk \
 	     uio.expected \
+	     umovestr.expected \
 	     unix-yy-accept.awk \
 	     unix-yy-connect.awk \
 	     $(TESTS)
diff --git a/tests/caps.awk b/tests/caps.awk
index 70f3147..f2f143d 100644
--- a/tests/caps.awk
+++ b/tests/caps.awk
@@ -1,25 +1,12 @@
 BEGIN {
-  fail = 0
-  lines = 3
-  cap = "(0|CAP_[A-Z_]+(\\|CAP_[A-Z_]+)*|CAP_[A-Z_]+(\\|CAP_[A-Z_]+){37}\\|0xffffffc0)"
-  capget = "^capget\\(\\{_LINUX_CAPABILITY_VERSION_3, 0\\}, \\{" cap ", " cap ", " cap "\\}\\) = 0$"
+	cap = "(0|CAP_[A-Z_]+(\\|CAP_[A-Z_]+)*|CAP_[A-Z_]+(\\|CAP_[A-Z_]+){37}\\|0xffffffc0)"
+	r[1] = "^capget\\(\\{_LINUX_CAPABILITY_VERSION_3, 0\\}, \\{" cap ", " cap ", " cap "\\}\\) = 0$"
+	capset_data = "{CAP_DAC_OVERRIDE|CAP_WAKE_ALARM, CAP_DAC_READ_SEARCH|CAP_BLOCK_SUSPEND, 0}"
+	s[2] = "capset({_LINUX_CAPABILITY_VERSION_3, 0}, " capset_data ") = -1 EPERM (Operation not permitted)"
+	s[3] = "+++ exited with 0 +++"
+
+	lines = 3
+	fail = 0
 }
 
-NR == 1 {if (match($0, capget)) next}
-
-NR == 2 && $0 == "capset({_LINUX_CAPABILITY_VERSION_3, 0}, {CAP_DAC_OVERRIDE|CAP_WAKE_ALARM, CAP_DAC_READ_SEARCH|CAP_BLOCK_SUSPEND, 0}) = -1 EPERM (Operation not permitted)" {next}
-
-NR == lines && $0 == "+++ exited with 0 +++" {next}
-
-{
-  print "Line " NR " does not match."
-  fail = 1
-  exit 1
-}
-
-END {
-  if (fail == 0 && NR != lines) {
-    print "Expected " lines " lines, found " NR " line(s)."
-    exit 1
-  }
-}
+@include "match.awk"
diff --git a/tests/getdents.awk b/tests/getdents.awk
index c230e26..8a00133 100644
--- a/tests/getdents.awk
+++ b/tests/getdents.awk
@@ -1,68 +1,51 @@
 BEGIN {
-  lines = 3
-  fail = 0
+	i = "[0-9]+"
+	len = "[1-9]" i
 
-  i = "[0-9]+"
-  len = "[1-9]" i
+	d_ino = "d_ino=" i
+	d_off = "d_off=" i
+	d_reclen = "d_reclen=" len
+	d_name_1 = "d_name=\"\\.\""
+	d_name_2 = "d_name=\"\\.\\.\""
+	d_name_3 = "d_name=\"(A\\\\n){127}Z\""
+	# Some older systems might not pass back d_type at all like Alpha.
+	d_type_dir = "d_type=DT_(DIR|UNKNOWN)"
+	d_type_reg = "d_type=DT_(REG|UNKNOWN)"
 
-  d_ino = "d_ino=" i
-  d_off = "d_off=" i
-  d_reclen = "d_reclen=" len
-  d_name_1 = "d_name=\"\\.\""
-  d_name_2 = "d_name=\"\\.\\.\""
-  d_name_3 = "d_name=\"(A\\\\n){127}Z\""
-  # Some older systems might not pass back d_type at all like Alpha.
-  d_type_dir = "d_type=DT_(DIR|UNKNOWN)"
-  d_type_reg = "d_type=DT_(REG|UNKNOWN)"
+	dirent_1   = "\\{" d_ino ", " d_off ", " d_reclen ", " d_name_1 ", " d_type_dir "\\}"
+	dirent_2   = "\\{" d_ino ", " d_off ", " d_reclen ", " d_name_2 ", " d_type_dir "\\}"
+	dirent_3   = "\\{" d_ino ", " d_off ", " d_reclen ", " d_name_3 ", " d_type_reg "\\}"
 
-  dirent_1   = "\\{" d_ino ", " d_off ", " d_reclen ", " d_name_1 ", " d_type_dir "\\}"
-  dirent_2   = "\\{" d_ino ", " d_off ", " d_reclen ", " d_name_2 ", " d_type_dir "\\}"
-  dirent_3   = "\\{" d_ino ", " d_off ", " d_reclen ", " d_name_3 ", " d_type_reg "\\}"
+	dirent64_1 = "\\{" d_ino ", " d_off ", " d_reclen ", " d_type_dir ", " d_name_1 "\\}"
+	dirent64_2 = "\\{" d_ino ", " d_off ", " d_reclen ", " d_type_dir ", " d_name_2 "\\}"
+	dirent64_3 = "\\{" d_ino ", " d_off ", " d_reclen ", " d_type_reg ", " d_name_3 "\\}"
 
-  dirent64_1 = "\\{" d_ino ", " d_off ", " d_reclen ", " d_type_dir ", " d_name_1 "\\}"
-  dirent64_2 = "\\{" d_ino ", " d_off ", " d_reclen ", " d_type_dir ", " d_name_2 "\\}"
-  dirent64_3 = "\\{" d_ino ", " d_off ", " d_reclen ", " d_type_reg ", " d_name_3 "\\}"
+	d_123 = dirent_1 " " dirent_2 " " dirent_3
+	d_213 = dirent_2 " " dirent_1 " " dirent_3
+	d_132 = dirent_1 " " dirent_3 " " dirent_2
+	d_321 = dirent_3 " " dirent_2 " " dirent_1
+	d_231 = dirent_2 " " dirent_3 " " dirent_1
+	d_312 = dirent_3 " " dirent_1 " " dirent_2
 
-  d_123 = dirent_1 " " dirent_2 " " dirent_3
-  d_213 = dirent_2 " " dirent_1 " " dirent_3
-  d_132 = dirent_1 " " dirent_3 " " dirent_2
-  d_321 = dirent_3 " " dirent_2 " " dirent_1
-  d_231 = dirent_2 " " dirent_3 " " dirent_1
-  d_312 = dirent_3 " " dirent_1 " " dirent_2
+	d64_123 = dirent64_1 " " dirent64_2 " " dirent64_3
+	d64_213 = dirent64_2 " " dirent64_1 " " dirent64_3
+	d64_132 = dirent64_1 " " dirent64_3 " " dirent64_2
+	d64_321 = dirent64_3 " " dirent64_2 " " dirent64_1
+	d64_231 = dirent64_2 " " dirent64_3 " " dirent64_1
+	d64_312 = dirent64_3 " " dirent64_1 " " dirent64_2
 
-  d64_123 = dirent64_1 " " dirent64_2 " " dirent64_3
-  d64_213 = dirent64_2 " " dirent64_1 " " dirent64_3
-  d64_132 = dirent64_1 " " dirent64_3 " " dirent64_2
-  d64_321 = dirent64_3 " " dirent64_2 " " dirent64_1
-  d64_231 = dirent64_2 " " dirent64_3 " " dirent64_1
-  d64_312 = dirent64_3 " " dirent64_1 " " dirent64_2
+	dents = "\\{(" d_123 "|" d_213 "|" d_132 "|" d_321 "|" d_231 "|" d_312 ")\\}"
+	dents64 = "\\{(" d64_123 "|" d64_213 "|" d64_132 "|" d64_321 "|" d64_231 "|" d64_312 ")\\}"
 
-  dents = "\\{(" d_123 "|" d_213 "|" d_132 "|" d_321 "|" d_231 "|" d_312 ")\\}"
-  dents64 = "\\{(" d64_123 "|" d64_213 "|" d64_132 "|" d64_321 "|" d64_231 "|" d64_312 ")\\}"
+	getdents   =   "getdents\\(" i ", " dents   ", " len "\\)"
+	getdents64 = "getdents64\\(" i ", " dents64 ", " len "\\)"
 
-  getdents   =   "^getdents\\(" i ", " dents   ", " len "\\) += " len "$"
-  getdents64 = "^getdents64\\(" i ", " dents64 ", " len "\\) += " len "$"
+	r[1] = "^(" getdents "|" getdents64 ") += " len "$"
+	r[2] = "^getdents(64)?\\([0-9]+, \\{\\}, [1-9][0-9]+\\) += 0$"
+	s[3] = "+++ exited with 0 +++"
+
+	lines = 3
+	fail = 0
 }
 
-NR == 1 {if (match($0, getdents) || match($0, getdents64)) next}
-
-NR == 2 && /^getdents(64)?\([0-9]+, \{\}, [1-9][0-9]+\) += 0$/ {next}
-
-NR == lines && /^\+\+\+ exited with 0 \+\+\+$/ {next}
-
-{
-  print "Line " NR " does not match: " $0
-  fail=1
-}
-
-END {
-  if (NR != lines) {
-    print "Expected " lines " lines, found " NR " line(s)."
-    print ""
-    exit 1
-  }
-  if (fail) {
-    print ""
-    exit 1
-  }
-}
+@include "match.awk"
diff --git a/tests/getdents.test b/tests/getdents.test
index 5be3e83..3fa1c8d 100755
--- a/tests/getdents.test
+++ b/tests/getdents.test
@@ -4,9 +4,9 @@
 
 . "${srcdir=.}/init.sh"
 
-check_prog awk
-awk -f "$srcdir"/getdents.awk "$srcdir"/getdents.out ||
-	framework_skip_ 'awk does not work properly'
+check_prog gawk
+AWKPATH="$srcdir" gawk -f "$srcdir"/getdents.awk "$srcdir"/getdents.out ||
+	framework_skip_ 'gawk does not work properly'
 
 check_prog ls
 check_prog mkdir
diff --git a/tests/getrandom.awk b/tests/getrandom.awk
index 4c5f6fc..09d2a0f 100644
--- a/tests/getrandom.awk
+++ b/tests/getrandom.awk
@@ -2,25 +2,10 @@
 	r[1] = "^getrandom\\(\"(\\\\x[0-9a-f][0-9a-f]){3}\", 3, 0\\) += 3$"
 	r[2] = "^getrandom\\(\"(\\\\x[0-9a-f][0-9a-f]){3}\"\\.\\.\\., 4, GRND_NONBLOCK\\) += 4$"
 	r[3] = "^getrandom\\(0x[[0-9a-f]+, 4, GRND_NONBLOCK\\|GRND_RANDOM\\|0x3000\\) += -1 "
-	r[4] = "^\\+\\+\\+ exited with 0 \\+\\+\\+$"
+	s[4] = "+++ exited with 0 +++"
+
 	lines = 4
 	fail = 0
 }
 
-NR > lines { exit 1 }
-
-{
-	if (match($0, r[NR]))
-		next
-
-	print "Line " NR " does not match."
-	fail = 1
-}
-
-END {
-	if (fail == 0 && NR != lines) {
-		fail = 1
-		print "Expected " lines " lines, found " NR " line(s)."
-	}
-	exit fail
-}
+@include "match.awk"
diff --git a/tests/init.sh b/tests/init.sh
index a3ccd1f..c976806 100644
--- a/tests/init.sh
+++ b/tests/init.sh
@@ -59,6 +59,18 @@
 	rm -f -- "$LOG".[0-9]*
 }
 
+check_gawk()
+{
+	check_prog gawk
+	check_prog grep
+
+	local program="$1"; shift
+	if grep '^@include[[:space:]]' < "$program" > /dev/null; then
+		gawk '@include "/dev/null"' < /dev/null ||
+			framework_skip_ 'gawk does not support @include'
+	fi
+}
+
 # Usage: [FILE_TO_CHECK [AWK_PROGRAM [ERROR_MESSAGE [EXTRA_AWK_OPTIONS...]]]]
 # Check whether all patterns listed in AWK_PROGRAM
 # match FILE_TO_CHECK using egrep.
@@ -66,7 +78,7 @@
 # dump both files and fail with ERROR_MESSAGE.
 match_awk()
 {
-	local output program error awk
+	local output program error
 	if [ $# -eq 0 ]; then
 		output="$LOG"
 	else
@@ -82,11 +94,10 @@
 	else
 		error="$1"; shift
 	fi
-	awk=${AWK:-awk}
 
-	check_prog "$awk"
+	check_gawk "$program"
 
-	"$awk" -f "$program" "$@" < "$output" || {
+	AWKPATH="$srcdir" gawk -f "$program" "$@" < "$output" || {
 		cat < "$output"
 		fail_ "$error"
 	}
diff --git a/tests/match.awk b/tests/match.awk
new file mode 100644
index 0000000..39af47c
--- /dev/null
+++ b/tests/match.awk
@@ -0,0 +1,26 @@
+# s[] is array of match strings
+# r[] is array of match patterns
+
+NR > lines { next }
+
+{
+	if (s[NR]) {
+		if ($0 == s[NR])
+			next
+		print "Line " NR " does not match expected string: " s[NR]
+	} else {
+		if (match($0, r[NR]))
+			next
+		print "Line " NR " does not match expected pattern: " r[NR]
+	}
+
+	fail = 1
+}
+
+END {
+	if (fail == 0 && NR != lines) {
+		fail = 1
+		print "Expected " lines " lines, found " NR " line(s)."
+	}
+	exit fail
+}
diff --git a/tests/mmap.c b/tests/mmap.c
new file mode 100644
index 0000000..d4d3e66
--- /dev/null
+++ b/tests/mmap.c
@@ -0,0 +1,46 @@
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <stdio.h>
+#include <stdint.h>
+#include <unistd.h>
+#include <limits.h>
+#include <sys/mman.h>
+
+int
+main(void)
+{
+	const intmax_t pagesize = sysconf(_SC_PAGESIZE);
+	const unsigned long length = pagesize * 3;
+	const int fd = -1;
+	off_t offset;
+	void *addr, *p;
+
+#if ULONG_MAX > 4294967295UL
+	offset = 0xcafedeadbeef000 & -pagesize;
+	addr = (void *) (uintmax_t) (0xfacefeed000 & -pagesize);
+#else
+	offset = 0xdeadbeef000 & -pagesize;
+	addr = (void *) (unsigned int) (0xfaced000 & -pagesize);
+#endif
+
+	p = mmap(addr, length, PROT_READ | PROT_WRITE,
+		 MAP_PRIVATE | MAP_ANONYMOUS, fd, offset);
+	if (p == MAP_FAILED ||
+	    mprotect(p, length, PROT_NONE) ||
+	    munmap(p, length))
+		return 77;
+
+	if (sizeof(offset) == sizeof(int))
+		printf("(mmap2?|old_mmap)\\(%p, %lu, PROT_READ\\|PROT_WRITE, "
+		       "MAP_PRIVATE\\|MAP_ANONYMOUS, %d, %#x\\) = %p\n",
+		       addr, length, fd, (unsigned int) offset, p);
+	else
+		printf("(mmap2?|old_mmap)\\(%p, %lu, PROT_READ\\|PROT_WRITE, "
+		       "MAP_PRIVATE\\|MAP_ANONYMOUS, %d, %#jx\\) = %p\n",
+		       addr, length, fd, (uintmax_t) offset, p);
+	printf("mprotect\\(%p, %lu, PROT_NONE\\) += 0\n", p, length);
+	printf("munmap\\(%p, %lu\\) += 0\n", p, length);
+	return 0;
+}
diff --git a/tests/mmap.test b/tests/mmap.test
new file mode 100755
index 0000000..e9c9b3a
--- /dev/null
+++ b/tests/mmap.test
@@ -0,0 +1,20 @@
+#!/bin/sh
+
+# Check mmap/mprotect/munmap syscalls decoding.
+
+. "${srcdir=.}/init.sh"
+
+syscall=mprotect,munmap
+for n in mmap mmap2 old_mmap; do
+	$STRACE -e$n -h > /dev/null && syscall=$syscall,$n
+done
+
+OUT="$LOG.out"
+
+run_prog > /dev/null
+run_strace -e$syscall $args > "$OUT"
+match_grep "$LOG" "$OUT"
+
+rm -f "$OUT"
+
+exit 0
diff --git a/tests/mmap64.c b/tests/mmap64.c
new file mode 100644
index 0000000..b31ce42
--- /dev/null
+++ b/tests/mmap64.c
@@ -0,0 +1 @@
+#include "mmap.c"
diff --git a/tests/mmap64.test b/tests/mmap64.test
new file mode 100755
index 0000000..51f1896
--- /dev/null
+++ b/tests/mmap64.test
@@ -0,0 +1,6 @@
+#!/bin/sh
+
+# Check mmap/mprotect/munmap syscalls decoding.
+# Target executable was compiled with -D_FILE_OFFSET_BITS=64.
+
+. "${srcdir=.}/mmap.test"
diff --git a/tests/netlink_inet_diag.c b/tests/netlink_inet_diag.c
index 7d41b0b..bacb938 100644
--- a/tests/netlink_inet_diag.c
+++ b/tests/netlink_inet_diag.c
@@ -81,11 +81,10 @@
 	close(0);
 	close(1);
 
-	assert(socket(PF_INET, SOCK_STREAM, 0) == 0);
-	assert(bind(0, (struct sockaddr *) &addr, len) == 0);
-	assert(listen(0, 5) == 0);
-
-	if (socket(AF_NETLINK, SOCK_RAW, NETLINK_INET_DIAG) != 1)
+	if (socket(PF_INET, SOCK_STREAM, 0) ||
+	    bind(0, (struct sockaddr *) &addr, len) ||
+	    listen(0, 5) ||
+	    socket(AF_NETLINK, SOCK_RAW, NETLINK_INET_DIAG) != 1)
 		return 77;
 
 	return (send_query(1, AF_INET, IPPROTO_TCP) &&
diff --git a/tests/netlink_unix_diag.c b/tests/netlink_unix_diag.c
index 979ab88..817bf01 100644
--- a/tests/netlink_unix_diag.c
+++ b/tests/netlink_unix_diag.c
@@ -90,9 +90,11 @@
 	close(1);
 
 	(void) unlink(SUN_PATH);
-	assert(socket(PF_LOCAL, SOCK_STREAM, 0) == 0);
-	assert(bind(0, (struct sockaddr *) &addr, len) == 0);
-	assert(listen(0, 5) == 0);
+	if (socket(PF_LOCAL, SOCK_STREAM, 0) ||
+	    bind(0, (struct sockaddr *) &addr, len) ||
+	    listen(0, 5))
+		return 77;
+
 	assert(unlink(SUN_PATH) == 0);
 
 	if (socket(AF_NETLINK, SOCK_RAW, NETLINK_SOCK_DIAG) != 1)
diff --git a/tests/pipe.c b/tests/pipe.c
new file mode 100644
index 0000000..6a5306f
--- /dev/null
+++ b/tests/pipe.c
@@ -0,0 +1,27 @@
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <stdio.h>
+#include <fcntl.h>
+#include <unistd.h>
+
+int
+main(void)
+{
+	(void) close(0);
+	(void) close(1);
+	int fds[2];
+	if (pipe(fds) || fds[0] != 0 || fds[1] != 1)
+		return 77;
+
+#ifdef HAVE_PIPE2
+	(void) close(0);
+	(void) close(1);
+	if (pipe2(fds, O_NONBLOCK) || fds[0] != 0 || fds[1] != 1)
+		return 77;
+	return 0;
+#else
+	return 77;
+#endif
+}
diff --git a/tests/pipe.expected b/tests/pipe.expected
new file mode 100644
index 0000000..675cb85
--- /dev/null
+++ b/tests/pipe.expected
@@ -0,0 +1,2 @@
+pipe(\(\[0, 1\]|2\(\[0, 1\], 0)\) += 0
+pipe2\(\[0, 1\], O_NONBLOCK\) += 0
diff --git a/tests/pipe.test b/tests/pipe.test
new file mode 100755
index 0000000..a445f86
--- /dev/null
+++ b/tests/pipe.test
@@ -0,0 +1,16 @@
+#!/bin/sh
+
+# Check pipe/pipe2 syscalls decoding.
+
+. "${srcdir=.}/init.sh"
+
+syscall=pipe2
+for n in pipe; do
+	$STRACE -e$n -h > /dev/null && syscall=$syscall,$n
+done
+
+run_prog
+run_strace -e$syscall $args
+match_grep
+
+exit 0
diff --git a/tests/seccomp.c b/tests/seccomp.c
new file mode 100644
index 0000000..01fe2eb
--- /dev/null
+++ b/tests/seccomp.c
@@ -0,0 +1,113 @@
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <stddef.h>
+#include <unistd.h>
+#include <stdio.h>
+#include <errno.h>
+#include <sys/syscall.h>
+
+#ifdef HAVE_PRCTL
+# include <sys/prctl.h>
+#endif
+#ifdef HAVE_LINUX_SECCOMP_H
+# include <linux/seccomp.h>
+#endif
+#ifdef HAVE_LINUX_FILTER_H
+# include <linux/filter.h>
+#endif
+
+#if defined HAVE_PRCTL \
+ && defined PR_SET_NO_NEW_PRIVS \
+ && defined PR_SET_SECCOMP \
+ && defined SECCOMP_MODE_FILTER \
+ && defined SECCOMP_RET_ERRNO \
+ && defined BPF_JUMP \
+ && defined BPF_STMT
+
+#define SOCK_FILTER_ALLOW_SYSCALL(nr) \
+		BPF_JUMP(BPF_JMP | BPF_K | BPF_JEQ, __NR_ ## nr, 0, 1), \
+		BPF_STMT(BPF_RET | BPF_K, SECCOMP_RET_ALLOW)
+
+#define SOCK_FILTER_DENY_SYSCALL(nr, err) \
+		BPF_JUMP(BPF_JMP | BPF_K | BPF_JEQ, __NR_ ## nr, 0, 1), \
+		BPF_STMT(BPF_RET | BPF_K, SECCOMP_RET_ERRNO | (SECCOMP_RET_DATA & (err)))
+
+#define SOCK_FILTER_KILL_PROCESS \
+		BPF_STMT(BPF_RET | BPF_K, SECCOMP_RET_KILL)
+
+#define PRINT_ALLOW_SYSCALL(nr) \
+	printf("BPF_JUMP(BPF_JMP | BPF_K | BPF_JEQ, %#x, 0, 0x1), " \
+	       "BPF_STMT(BPF_RET | BPF_K, SECCOMP_RET_ALLOW), ", \
+	       __NR_ ## nr)
+
+#define PRINT_DENY_SYSCALL(nr, err) \
+	printf("BPF_JUMP(BPF_JMP | BPF_K | BPF_JEQ, %#x, 0, 0x1), " \
+	       "BPF_STMT(BPF_RET | BPF_K, SECCOMP_RET_ERRNO | %#x), ", \
+	       __NR_ ## nr, err)
+
+static const struct sock_filter filter[] = {
+	/* load syscall number */
+	BPF_STMT(BPF_LD | BPF_W | BPF_ABS, offsetof(struct seccomp_data, nr)),
+
+	/* allow syscalls */
+	SOCK_FILTER_ALLOW_SYSCALL(close),
+	SOCK_FILTER_ALLOW_SYSCALL(exit),
+	SOCK_FILTER_ALLOW_SYSCALL(exit_group),
+
+	/* deny syscalls */
+	SOCK_FILTER_DENY_SYSCALL(sync, EBUSY),
+	SOCK_FILTER_DENY_SYSCALL(setsid, EPERM),
+
+	/* kill process */
+	SOCK_FILTER_KILL_PROCESS
+};
+
+static const struct sock_fprog prog = {
+	.len = sizeof(filter) / sizeof(filter[0]),
+	.filter = (struct sock_filter *) filter,
+};
+
+int
+main(void)
+{
+	int fds[2];
+
+	puts("prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0)  = 0");
+
+	printf("prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, [");
+
+	printf("BPF_STMT(BPF_LD | BPF_W | BPF_ABS, %#x), ",
+	       (unsigned) offsetof(struct seccomp_data, nr));
+
+	PRINT_ALLOW_SYSCALL(close);
+	PRINT_ALLOW_SYSCALL(exit);
+	PRINT_ALLOW_SYSCALL(exit_group);
+
+	PRINT_DENY_SYSCALL(sync, EBUSY),
+	PRINT_DENY_SYSCALL(setsid, EPERM),
+
+	printf("BPF_STMT(BPF_RET | BPF_K, SECCOMP_RET_KILL)");
+
+	puts("]) = 0");
+	puts("+++ exited with 0 +++");
+
+	fflush(stdout);
+	close(0);
+	close(1);
+
+	if (pipe(fds) ||
+	    prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0) ||
+	    prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &prog) ||
+	    close(0) || close(1))
+		_exit(77);
+
+	_exit(0);
+}
+
+#else
+
+int main(void) { return 77; }
+
+#endif
diff --git a/tests/seccomp.test b/tests/seccomp.test
new file mode 100755
index 0000000..4101cae
--- /dev/null
+++ b/tests/seccomp.test
@@ -0,0 +1,15 @@
+#!/bin/sh
+
+# Check how SECCOMP_MODE_FILTER is decoded.
+
+. "${srcdir=.}/init.sh"
+
+OUT="$LOG.out"
+
+run_prog > /dev/null
+run_strace -veprctl $args > "$OUT"
+match_diff "$LOG" "$OUT"
+
+rm -f "$OUT"
+
+exit 0
diff --git a/tests/select.awk b/tests/select.awk
index 688cefe..996d028 100644
--- a/tests/select.awk
+++ b/tests/select.awk
@@ -2,25 +2,10 @@
 	r[1] = "^p?select6?\\(2, \\[0 1\\], \\[0 1\\], \\[0 1\\], NULL(, 0)?\\) += 1 \\(\\)$"
 	r[2] = "^p?select6?\\(-1, NULL, 0x[0-9a-f]+, NULL, NULL(, 0)?\\) += -1 "
 	r[3] = "^p?select6?\\(1025, \\[0\\], \\[\\], NULL, \\{0, 100(000)?\\}(, 0)?\\) += 0 \\(Timeout\\)$"
-	r[4] = "^\\+\\+\\+ exited with 0 \\+\\+\\+$"
+	s[4] = "+++ exited with 0 +++"
+
 	lines = 4
 	fail = 0
 }
 
-NR > lines { exit 1 }
-
-{
-	if (match($0, r[NR]))
-		next
-
-	print "Line " NR " does not match."
-	fail = 1
-}
-
-END {
-	if (fail == 0 && NR != lines) {
-		fail = 1
-		print "Expected " lines " lines, found " NR " line(s)."
-	}
-	exit fail
-}
+@include "match.awk"
diff --git a/tests/sigaction.awk b/tests/sigaction.awk
index 01133d2..df96e4b 100644
--- a/tests/sigaction.awk
+++ b/tests/sigaction.awk
@@ -1,55 +1,37 @@
-# rt_sigaction on ALPHA has 5 args: sig, act, oact, sigsetsize, restorer.
-# rt_sigaction on SPARC has 5 args: sig, act, oact, restorer, sigsetsize.
-# rt_sigaction on other architectures has 4 args: sig, act, oact, sigsetsize.
-# Some architectures have SA_RESTORER, some don't;
-# in particular, SPARC has and ALPHA hasn't.
-#
-# There are two regexps for each test:
-# the 1st is for any architecture with SA_RESTORER, including SPARC;
-# the 2nd is for any architecture without SA_RESTORER, including ALPHA;
-# the 3rd is for any architecture without SA_RESTORER and swapped args.
-
 BEGIN {
+	n1[1] = "SIG_IGN, \\[HUP INT\\], SA_RESTORER\\|SA_RESTART, 0x[0-9a-f]+"
+	n2[1] = "SIG_IGN, \\[HUP INT\\], SA_RESTART"
+
+	n1[2] = "0x[0-9a-f]+, \\[QUIT TERM\\], SA_RESTORER\\|SA_SIGINFO, 0x[0-9a-f]+"
+	n2[2] = "0x[0-9a-f]+, \\[QUIT TERM\\], SA_SIGINFO"
+
+	n1[3] = "SIG_DFL, \\[\\], SA_RESTORER, 0x[0-9a-f]+"
+	n2[3] = "SIG_DFL, \\[\\], 0"
+
+	n1[4] = "SIG_DFL, ~\\[HUP( ((RT|SIGRT)[^] ]+|[3-9][0-9]|1[0-9][0-9]))*\\], SA_RESTORER, 0x[0-9a-f]+"
+	n2[4] = "SIG_DFL, ~\\[HUP( ((RT|SIGRT)[^] ]+|[3-9][0-9]|1[0-9][0-9]))*\\], 0"
+
+	o1[1] = o2[1] = "SIG_DFL, \\[\\], 0"
+
+	for (i = 2; i < 5; i++) {
+		o1[i] = n1[i - 1]
+		o2[i] = n2[i - 1]
+	}
+
+	a1 = "(0x[0-9a-f]+, )?(4|8|16)"
+	a2 = "(4|8|16)(, 0x[0-9a-f]+)?"
+	a3 = "0x[0-9a-f]+, (4|8|16)"
+
+	for (i = 1; i < 5; i++) {
+		r[i] = "^rt_sigaction\\(SIGUSR2, (" \
+			"\\{" n1[i] "\\}, \\{" o1[i] "\\}, " a1 "|" \
+			"\\{" n2[i] "\\}, \\{" o2[i] "\\}, " a2 "|" \
+			"\\{" n2[i] "\\}, \\{" o2[i] "\\}, " a3 ")\\) = 0$"
+	}
+	s[5] = "+++ exited with 0 +++"
+
 	lines = 5
 	fail = 0
 }
 
-# Test 1.
-NR == 1 && /^rt_sigaction\(SIGUSR2, \{SIG_IGN, \[HUP INT\], SA_RESTORER\|SA_RESTART, 0x[0-9a-f]+\}, \{SIG_DFL, \[\], 0\}, (0x[0-9a-f]+, )?(4|8|16)\) = 0$/ {next}
-NR == 1 && /^rt_sigaction\(SIGUSR2, \{SIG_IGN, \[HUP INT\], SA_RESTART\}, \{SIG_DFL, \[\], 0\}, (4|8|16)(, 0x[0-9a-f]+)?\) = 0$/ {next}
-NR == 1 && /^rt_sigaction\(SIGUSR2, \{SIG_IGN, \[HUP INT\], SA_RESTART\}, \{SIG_DFL, \[\], 0\}, 0x[0-9a-f]+, (4|8|16)\) = 0$/ {next}
-
-# Test 2.
-NR == 2 && /^rt_sigaction\(SIGUSR2, \{0x[0-9a-f]+, \[QUIT TERM\], SA_RESTORER\|SA_SIGINFO, 0x[0-9a-f]+\}, \{SIG_IGN, \[HUP INT\], SA_RESTORER\|SA_RESTART, 0x[0-9a-f]+\}, (0x[0-9a-f]+, )?(4|8|16)\) = 0$/ {next}
-NR == 2 && /^rt_sigaction\(SIGUSR2, \{0x[0-9a-f]+, \[QUIT TERM\], SA_SIGINFO\}, \{SIG_IGN, \[HUP INT\], SA_RESTART\}, (4|8|16)(, 0x[0-9a-f]+)?\) = 0$/ {next}
-NR == 2 && /^rt_sigaction\(SIGUSR2, \{0x[0-9a-f]+, \[QUIT TERM\], SA_SIGINFO\}, \{SIG_IGN, \[HUP INT\], SA_RESTART\}, 0x[0-9a-f]+, (4|8|16)\) = 0$/ {next}
-
-# Test 3.
-NR == 3 && /^rt_sigaction\(SIGUSR2, \{SIG_DFL, \[\], SA_RESTORER, 0x[0-9a-f]+\}, \{0x[0-9a-f]+, \[QUIT TERM\], SA_RESTORER\|SA_SIGINFO, 0x[0-9a-f]+\}, (0x[0-9a-f]+, )?(4|8|16)\) = 0$/ {next}
-NR == 3 && /^rt_sigaction\(SIGUSR2, \{SIG_DFL, \[\], 0\}, \{0x[0-9a-f]+, \[QUIT TERM\], SA_SIGINFO\}, (4|8|16)(, 0x[0-9a-f]+)?\) = 0$/ {next}
-NR == 3 && /^rt_sigaction\(SIGUSR2, \{SIG_DFL, \[\], 0\}, \{0x[0-9a-f]+, \[QUIT TERM\], SA_SIGINFO\}, 0x[0-9a-f]+, (4|8|16)\) = 0$/ {next}
-
-# Test 4.
-NR == 4 && /^rt_sigaction\(SIGUSR2, \{SIG_DFL, ~\[HUP( ((RT|SIGRT)[^] ]+|[3-9][0-9]|1[0-9][0-9]))*\], SA_RESTORER, 0x[0-9a-f]+\}, \{SIG_DFL, \[\], SA_RESTORER, 0x[0-9a-f]+\}, (0x[0-9a-f]+, )?(4|8|16)\) = 0$/ {next}
-NR == 4 && /^rt_sigaction\(SIGUSR2, \{SIG_DFL, ~\[HUP( ((RT|SIGRT)[^] ]+|[3-9][0-9]|1[0-9][0-9]))*\], 0\}, \{SIG_DFL, \[\], 0\}, (4|8|16)(, 0x[0-9a-f]+)?\) = 0$/ {next}
-NR == 4 && /^rt_sigaction\(SIGUSR2, \{SIG_DFL, ~\[HUP( ((RT|SIGRT)[^] ]+|[3-9][0-9]|1[0-9][0-9]))*\], 0\}, \{SIG_DFL, \[\], 0\}, 0x[0-9a-f]+, (4|8|16)\) = 0$/ {next}
-
-# The last line.
-NR == lines && /^\+\+\+ exited with 0 \+\+\+$/ {next}
-
-{
-  print "Line " NR " does not match: " $0
-  fail=1
-}
-
-END {
-  if (NR != lines) {
-    print "Expected " lines " lines, found " NR " line(s)."
-    print ""
-    exit 1
-  }
-  if (fail) {
-    print ""
-    exit 1
-  }
-}
+@include "match.awk"
diff --git a/tests/umovestr.c b/tests/umovestr.c
new file mode 100644
index 0000000..9ad6b94
--- /dev/null
+++ b/tests/umovestr.c
@@ -0,0 +1,26 @@
+#include <string.h>
+#include <unistd.h>
+#include <sys/mman.h>
+
+int
+main(void)
+{
+	const size_t page_len = sysconf(_SC_PAGESIZE);
+	const size_t tail_len = 257;
+
+	if (tail_len >= page_len)
+		return 77;
+
+	void *p = mmap(NULL, page_len * 2, PROT_READ | PROT_WRITE,
+		       MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
+	if (p == MAP_FAILED || mprotect(p + page_len, page_len, PROT_NONE))
+		return 77;
+
+	memset(p, 0, page_len);
+	char *addr = p + page_len - tail_len;
+	memset(addr, '/', tail_len - 1);
+	if (chdir(addr))
+		return 77;
+
+	return 0;
+}
diff --git a/tests/umovestr.expected b/tests/umovestr.expected
new file mode 100644
index 0000000..c26d877
--- /dev/null
+++ b/tests/umovestr.expected
@@ -0,0 +1,2 @@
+chdir("////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////") = 0
++++ exited with 0 +++
diff --git a/tests/umovestr.test b/tests/umovestr.test
new file mode 100755
index 0000000..5ae8ffa
--- /dev/null
+++ b/tests/umovestr.test
@@ -0,0 +1,11 @@
+#!/bin/sh
+
+# umovestr short read regression test
+
+. "${srcdir=.}/init.sh"
+
+run_prog
+run_strace -e chdir $args
+match_diff
+
+exit 0
diff --git a/tests/umovestr2.c b/tests/umovestr2.c
new file mode 100644
index 0000000..c7bd42f
--- /dev/null
+++ b/tests/umovestr2.c
@@ -0,0 +1,31 @@
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+#include <sys/mman.h>
+
+int
+main(void)
+{
+	const size_t page_len = sysconf(_SC_PAGESIZE);
+	const size_t work_len = page_len * 2;
+	const size_t tail_len = work_len - 1;
+
+	void *p = mmap(NULL, page_len * 3, PROT_READ | PROT_WRITE,
+		       MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
+	if (p == MAP_FAILED || mprotect(p + work_len, page_len, PROT_NONE))
+		return 77;
+
+	memset(p, 0, work_len);
+	char *addr = p + work_len - tail_len;
+	memset(addr, '0', tail_len - 1);
+
+	char *argv[] = { NULL };
+	char *envp[] = { addr, NULL };
+	execve("", argv, envp);
+
+	printf("execve(\"\", [], [\"%0*u\"]) = -1 ENOENT (No such file or directory)\n",
+	       (int) tail_len - 1, 0);
+	puts("+++ exited with 0 +++");
+
+	return 0;
+}
diff --git a/tests/umovestr2.test b/tests/umovestr2.test
new file mode 100755
index 0000000..2e9fee4
--- /dev/null
+++ b/tests/umovestr2.test
@@ -0,0 +1,18 @@
+#!/bin/sh
+
+# umovestr short read regression test
+
+. "${srcdir=.}/init.sh"
+
+OUT="$LOG.out"
+EXP="$LOG.exp"
+
+run_prog > /dev/null
+run_strace -veexecve -s262144 $args > "$EXP"
+check_prog sed
+sed 1d < "$LOG" > "$OUT"
+match_diff "$OUT" "$EXP"
+
+rm -f "$EXP" "$OUT"
+
+exit 0
diff --git a/uid.c b/uid.c
index 1f8c365..96b3d38 100644
--- a/uid.c
+++ b/uid.c
@@ -183,7 +183,7 @@
 				tprints("...");
 				break;
 			}
-			if (umoven(tcp, cur, sizeof(gid), (char *) &gid) < 0) {
+			if (umoven(tcp, cur, sizeof(gid), &gid) < 0) {
 				tprints("?");
 				failed = 1;
 				break;
@@ -242,7 +242,7 @@
 				tprints("...");
 				break;
 			}
-			if (umoven(tcp, cur, sizeof(gid), (char *) &gid) < 0) {
+			if (umoven(tcp, cur, sizeof(gid), &gid) < 0) {
 				tprints("?");
 				failed = 1;
 				break;
diff --git a/util.c b/util.c
index 02c5b9a..6afafbb 100644
--- a/util.c
+++ b/util.c
@@ -835,7 +835,7 @@
 		fprintf(stderr, "Out of memory\n");
 		return;
 	}
-	if (umoven(tcp, addr, size, (char *) iov) >= 0) {
+	if (umoven(tcp, addr, size, iov) >= 0) {
 		for (i = 0; i < len; i++) {
 			/* include the buffer number to make it easy to
 			 * match up the trace with the source */
@@ -881,7 +881,7 @@
 		strsize = len + 16;
 	}
 
-	if (umoven(tcp, addr, len, (char *) str) < 0)
+	if (umoven(tcp, addr, len, str) < 0)
 		return;
 
 	/* Space-pad to 16 bytes */
@@ -963,14 +963,29 @@
 
 #endif /* end of hack */
 
-#define PAGMASK	(~(PAGSIZ - 1))
+static ssize_t
+vm_read_mem(pid_t pid, void *laddr, long raddr, size_t len)
+{
+	const struct iovec local = {
+		.iov_base = laddr,
+		.iov_len = len
+	};
+	const struct iovec remote = {
+		.iov_base = (void *) raddr,
+		.iov_len = len
+	};
+
+	return process_vm_readv(pid, &local, 1, &remote, 1, 0);
+}
+
 /*
  * move `len' bytes of data from process `pid'
- * at address `addr' to our space at `laddr'
+ * at address `addr' to our space at `our_addr'
  */
 int
-umoven(struct tcb *tcp, long addr, unsigned int len, char *laddr)
+umoven(struct tcb *tcp, long addr, unsigned int len, void *our_addr)
 {
+	char *laddr = our_addr;
 	int pid = tcp->pid;
 	unsigned int n, m, nread;
 	union {
@@ -984,13 +999,7 @@
 #endif
 
 	if (!process_vm_readv_not_supported) {
-		struct iovec local[1], remote[1];
-		int r;
-
-		local[0].iov_base = laddr;
-		remote[0].iov_base = (void*)addr;
-		local[0].iov_len = remote[0].iov_len = len;
-		r = process_vm_readv(pid, local, 1, remote, 1, 0);
+		int r = vm_read_mem(pid, laddr, addr, len);
 		if ((unsigned int) r == len)
 			return 0;
 		if (r >= 0) {
@@ -1002,10 +1011,13 @@
 			case ENOSYS:
 				process_vm_readv_not_supported = 1;
 				break;
+			case EPERM:
+				/* operation not permitted, try PTRACE_PEEKDATA */
+				break;
 			case ESRCH:
 				/* the process is gone */
 				return -1;
-			case EFAULT: case EIO: case EPERM:
+			case EFAULT: case EIO:
 				/* address space is inaccessible */
 				return -1;
 			default:
@@ -1116,38 +1128,31 @@
 
 	nread = 0;
 	if (!process_vm_readv_not_supported) {
-		struct iovec local[1], remote[1];
-
-		local[0].iov_base = laddr;
-		remote[0].iov_base = (void*)addr;
+		const size_t page_size = get_pagesize();
+		const size_t page_mask = page_size - 1;
 
 		while (len > 0) {
 			unsigned int chunk_len;
 			unsigned int end_in_page;
-			int r;
 
-			/* Don't read kilobytes: most strings are short */
-			chunk_len = len;
-			if (chunk_len > 256)
-				chunk_len = 256;
-			/* Don't cross pages. I guess otherwise we can get EFAULT
+			/*
+			 * Don't cross pages, otherwise we can get EFAULT
 			 * and fail to notice that terminating NUL lies
 			 * in the existing (first) page.
-			 * (I hope there aren't arches with pages < 4K)
 			 */
-			end_in_page = ((addr + chunk_len) & 4095);
+			chunk_len = len > page_size ? page_size : len;
+			end_in_page = (addr + chunk_len) & page_mask;
 			if (chunk_len > end_in_page) /* crosses to the next page */
 				chunk_len -= end_in_page;
 
-			local[0].iov_len = remote[0].iov_len = chunk_len;
-			r = process_vm_readv(pid, local, 1, remote, 1, 0);
+			int r = vm_read_mem(pid, laddr, addr, chunk_len);
 			if (r > 0) {
-				if (memchr(local[0].iov_base, '\0', r))
+				if (memchr(laddr, '\0', r))
 					return 1;
-				local[0].iov_base += r;
-				remote[0].iov_base += r;
-				len -= r;
+				addr += r;
+				laddr += r;
 				nread += r;
+				len -= r;
 				continue;
 			}
 			switch (errno) {
@@ -1157,11 +1162,16 @@
 				case ESRCH:
 					/* the process is gone */
 					return -1;
-				case EFAULT: case EIO: case EPERM:
+				case EPERM:
+					/* operation not permitted, try PTRACE_PEEKDATA */
+					if (!nread)
+						goto vm_readv_didnt_work;
+					/* fall through */
+				case EFAULT: case EIO:
 					/* address space is inaccessible */
 					if (nread) {
 						perror_msg("umovestr: short read (%d < %d) @0x%lx",
-							   nread, nread + len, addr);
+							   nread, nread + len, addr - nread);
 					}
 					return -1;
 				default:
diff --git a/utime.c b/utime.c
index 6e396b0..ba25356 100644
--- a/utime.c
+++ b/utime.c
@@ -19,7 +19,7 @@
 			tprints("NULL");
 		else if (!verbose(tcp))
 			tprintf("%#lx", tcp->u_arg[1]);
-		else if (umoven(tcp, tcp->u_arg[1], 2 * wordsize, (char *) &u) < 0)
+		else if (umoven(tcp, tcp->u_arg[1], 2 * wordsize, &u) < 0)
 			tprints("[?, ?]");
 		else if (wordsize == sizeof u.utl[0]) {
 			tprintf("[%s,", sprinttime(u.utl[0]));
diff --git a/xlat/sigaltstack_flags.in b/xlat/sigaltstack_flags.in
index c27a931..376ec18 100644
--- a/xlat/sigaltstack_flags.in
+++ b/xlat/sigaltstack_flags.in
@@ -1,2 +1,2 @@
-SS_ONSTACK
-SS_DISABLE
+SS_ONSTACK 1
+SS_DISABLE 2
diff --git a/xlat/sigbus_codes.in b/xlat/sigbus_codes.in
index 8d8a048..1bce25f 100644
--- a/xlat/sigbus_codes.in
+++ b/xlat/sigbus_codes.in
@@ -1,3 +1,5 @@
-BUS_ADRALN
-BUS_ADRERR
-BUS_OBJERR
+BUS_ADRALN 1
+BUS_ADRERR 2
+BUS_OBJERR 3
+BUS_MCEERR_AR 4
+BUS_MCEERR_AO 5
diff --git a/xlat/sigchld_codes.in b/xlat/sigchld_codes.in
index 40c93ce..202bec4 100644
--- a/xlat/sigchld_codes.in
+++ b/xlat/sigchld_codes.in
@@ -1,6 +1,6 @@
-CLD_EXITED
-CLD_KILLED
-CLD_DUMPED
-CLD_TRAPPED
-CLD_STOPPED
-CLD_CONTINUED
+CLD_EXITED 1
+CLD_KILLED 2
+CLD_DUMPED 3
+CLD_TRAPPED 4
+CLD_STOPPED 5
+CLD_CONTINUED 6
diff --git a/xlat/sigemt_codes.in b/xlat/sigemt_codes.in
index 63fe3a3..eb87561 100644
--- a/xlat/sigemt_codes.in
+++ b/xlat/sigemt_codes.in
@@ -1 +1 @@
-EMT_TAGOVF
+EMT_TAGOVF 1
diff --git a/xlat/sigfpe_codes.in b/xlat/sigfpe_codes.in
index ab86b26..4ef0667 100644
--- a/xlat/sigfpe_codes.in
+++ b/xlat/sigfpe_codes.in
@@ -1,8 +1,8 @@
-FPE_INTDIV
-FPE_INTOVF
-FPE_FLTDIV
-FPE_FLTOVF
-FPE_FLTUND
-FPE_FLTRES
-FPE_FLTINV
-FPE_FLTSUB
+FPE_INTDIV 1
+FPE_INTOVF 2
+FPE_FLTDIV 3
+FPE_FLTOVF 4
+FPE_FLTUND 5
+FPE_FLTRES 6
+FPE_FLTINV 7
+FPE_FLTSUB 8
diff --git a/xlat/sigill_codes.in b/xlat/sigill_codes.in
index 6fb994e..ca111ec 100644
--- a/xlat/sigill_codes.in
+++ b/xlat/sigill_codes.in
@@ -1,8 +1,8 @@
-ILL_ILLOPC
-ILL_ILLOPN
-ILL_ILLADR
-ILL_ILLTRP
-ILL_PRVOPC
-ILL_PRVREG
-ILL_COPROC
-ILL_BADSTK
+ILL_ILLOPC 1
+ILL_ILLOPN 2
+ILL_ILLADR 3
+ILL_ILLTRP 4
+ILL_PRVOPC 5
+ILL_PRVREG 6
+ILL_COPROC 7
+ILL_BADSTK 8
diff --git a/xlat/siginfo_codes.in b/xlat/siginfo_codes.in
index 115d3ab..a57c370 100644
--- a/xlat/siginfo_codes.in
+++ b/xlat/siginfo_codes.in
@@ -1,12 +1,12 @@
-SI_KERNEL
-SI_USER
-SI_QUEUE
-SI_TIMER
-SI_MESGQ
-SI_ASYNCIO
-SI_SIGIO
-SI_TKILL
-SI_DETHREAD
-SI_ASYNCNL
+SI_USER 0
+SI_KERNEL 0x80
+SI_QUEUE -1
+SI_TIMER -2
+SI_MESGQ -3
+SI_ASYNCIO -4
+SI_SIGIO -5
+SI_TKILL -6
+SI_DETHREAD -7
+SI_ASYNCNL -60
 SI_NOINFO
 SI_LWP
diff --git a/xlat/sigpoll_codes.in b/xlat/sigpoll_codes.in
index f778fc6..00c2a1b 100644
--- a/xlat/sigpoll_codes.in
+++ b/xlat/sigpoll_codes.in
@@ -1,6 +1,6 @@
-POLL_IN
-POLL_OUT
-POLL_MSG
-POLL_ERR
-POLL_PRI
-POLL_HUP
+POLL_IN 1
+POLL_OUT 2
+POLL_MSG 3
+POLL_ERR 4
+POLL_PRI 5
+POLL_HUP 6
diff --git a/xlat/sigsegv_codes.in b/xlat/sigsegv_codes.in
index bdf3d7e..9117bc2 100644
--- a/xlat/sigsegv_codes.in
+++ b/xlat/sigsegv_codes.in
@@ -1,2 +1,3 @@
-SEGV_MAPERR
-SEGV_ACCERR
+SEGV_MAPERR 1
+SEGV_ACCERR 2
+SEGV_BNDERR 3
diff --git a/xlat/sigsys_codes.in b/xlat/sigsys_codes.in
index 7eaa40a..a8c4891 100644
--- a/xlat/sigsys_codes.in
+++ b/xlat/sigsys_codes.in
@@ -1 +1 @@
-SYS_SECCOMP
+SYS_SECCOMP 1
diff --git a/xlat/sigtrap_codes.in b/xlat/sigtrap_codes.in
index 41474fe..078aec8 100644
--- a/xlat/sigtrap_codes.in
+++ b/xlat/sigtrap_codes.in
@@ -1,2 +1,4 @@
-TRAP_BRKPT
-TRAP_TRACE
+TRAP_BRKPT 1
+TRAP_TRACE 2
+TRAP_BRANCH 3
+TRAP_HWBKPT 4