summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDmitry V. Levin <ldv@altlinux.org>2016-11-15 17:38:21 +0000
committerDmitry V. Levin <ldv@altlinux.org>2016-11-16 02:33:13 +0000
commitf1d0729f17023de3228cc2e1d7204a4c6bb91648 (patch)
tree76b151896147d913925bfb376f2a5f5cb656509d
parent05a3b0b518e3094509daccd642e069a1d18f4768 (diff)
downloadstrace-f1d0729f17023de3228cc2e1d7204a4c6bb91648.tar.gz
Implement arch specific methods of changing syscall number and error code
This introduces arch_set_error and arch_set_scno functions for each supported architecture, needed to implement syscall fault injection. * linux/aarch64/set_error.c: New file. * linux/aarch64/set_scno.c: Likewise. * linux/alpha/set_error.c: Likewise. * linux/alpha/set_scno.c: Likewise. * linux/arc/set_error.c: Likewise. * linux/arc/set_scno.c: Likewise. * linux/arm/set_error.c: Likewise. * linux/arm/set_scno.c: Likewise. * linux/avr32/set_error.c: Likewise. * linux/avr32/set_scno.c: Likewise. * linux/bfin/set_error.c: Likewise. * linux/bfin/set_scno.c: Likewise. * linux/crisv10/set_error.c: Likewise. * linux/crisv10/set_scno.c: Likewise. * linux/crisv32/set_error.c: Likewise. * linux/crisv32/set_scno.c: Likewise. * linux/hppa/set_error.c: Likewise. * linux/hppa/set_scno.c: Likewise. * linux/i386/set_error.c: Likewise. * linux/i386/set_scno.c: Likewise. * linux/ia64/set_error.c: Likewise. * linux/ia64/set_scno.c: Likewise. * linux/m68k/set_error.c: Likewise. * linux/m68k/set_scno.c: Likewise. * linux/metag/set_error.c: Likewise. * linux/metag/set_scno.c: Likewise. * linux/microblaze/set_error.c: Likewise. * linux/microblaze/set_scno.c: Likewise. * linux/mips/set_error.c: Likewise. * linux/mips/set_scno.c: Likewise. * linux/nios2/set_error.c: Likewise. * linux/nios2/set_scno.c: Likewise. * linux/or1k/set_error.c: Likewise. * linux/or1k/set_scno.c: Likewise. * linux/powerpc/set_error.c: Likewise. * linux/powerpc/set_scno.c: Likewise. * linux/powerpc64/set_error.c: Likewise. * linux/powerpc64/set_scno.c: Likewise. * linux/riscv/set_error.c: Likewise. * linux/riscv/set_scno.c: Likewise. * linux/s390/set_error.c: Likewise. * linux/s390/set_scno.c: Likewise. * linux/s390x/set_error.c: Likewise. * linux/s390x/set_scno.c: Likewise. * linux/sh/set_error.c: Likewise. * linux/sh/set_scno.c: Likewise. * linux/sh64/set_error.c: Likewise. * linux/sh64/set_scno.c: Likewise. * linux/sparc/set_error.c: Likewise. * linux/sparc/set_scno.c: Likewise. * linux/sparc64/set_error.c: Likewise. * linux/sparc64/set_scno.c: Likewise. * linux/tile/set_error.c: Likewise. * linux/tile/set_scno.c: Likewise. * linux/x32/set_error.c: Likewise. * linux/x32/set_scno.c: Likewise. * linux/x86_64/set_error.c: Likewise. * linux/x86_64/set_scno.c: Likewise. * linux/xtensa/set_error.c: Likewise. * linux/xtensa/set_scno.c: Likewise. * Makefile.am (EXTRA_DIST): Add them.
-rw-r--r--Makefile.am60
-rw-r--r--linux/aarch64/set_error.c13
-rw-r--r--linux/aarch64/set_scno.c18
-rw-r--r--linux/alpha/set_error.c6
-rw-r--r--linux/alpha/set_scno.c5
-rw-r--r--linux/arc/set_error.c6
-rw-r--r--linux/arc/set_scno.c6
-rw-r--r--linux/arm/set_error.c6
-rw-r--r--linux/arm/set_scno.c14
-rw-r--r--linux/avr32/set_error.c6
-rw-r--r--linux/avr32/set_scno.c6
-rw-r--r--linux/bfin/set_error.c6
-rw-r--r--linux/bfin/set_scno.c5
-rw-r--r--linux/crisv10/set_error.c6
-rw-r--r--linux/crisv10/set_scno.c5
-rw-r--r--linux/crisv32/set_error.c1
-rw-r--r--linux/crisv32/set_scno.c1
-rw-r--r--linux/hppa/set_error.c6
-rw-r--r--linux/hppa/set_scno.c5
-rw-r--r--linux/i386/set_error.c10
-rw-r--r--linux/i386/set_scno.c10
-rw-r--r--linux/ia64/set_error.c11
-rw-r--r--linux/ia64/set_scno.c10
-rw-r--r--linux/m68k/set_error.c6
-rw-r--r--linux/m68k/set_scno.c6
-rw-r--r--linux/metag/set_error.c6
-rw-r--r--linux/metag/set_scno.c6
-rw-r--r--linux/microblaze/set_error.c6
-rw-r--r--linux/microblaze/set_scno.c5
-rw-r--r--linux/mips/set_error.c7
-rw-r--r--linux/mips/set_scno.c6
-rw-r--r--linux/nios2/set_error.c7
-rw-r--r--linux/nios2/set_scno.c6
-rw-r--r--linux/or1k/set_error.c6
-rw-r--r--linux/or1k/set_scno.c6
-rw-r--r--linux/powerpc/set_error.c10
-rw-r--r--linux/powerpc/set_scno.c10
-rw-r--r--linux/powerpc64/set_error.c1
-rw-r--r--linux/powerpc64/set_scno.c1
-rw-r--r--linux/riscv/set_error.c6
-rw-r--r--linux/riscv/set_scno.c6
-rw-r--r--linux/s390/set_error.c6
-rw-r--r--linux/s390/set_scno.c6
-rw-r--r--linux/s390x/set_error.c1
-rw-r--r--linux/s390x/set_scno.c1
-rw-r--r--linux/sh/set_error.c6
-rw-r--r--linux/sh/set_scno.c5
-rw-r--r--linux/sh64/set_error.c6
-rw-r--r--linux/sh64/set_scno.c5
-rw-r--r--linux/sparc/set_error.c7
-rw-r--r--linux/sparc/set_scno.c6
-rw-r--r--linux/sparc64/set_error.c7
-rw-r--r--linux/sparc64/set_scno.c1
-rw-r--r--linux/tile/set_error.c6
-rw-r--r--linux/tile/set_scno.c6
-rw-r--r--linux/x32/set_error.c1
-rw-r--r--linux/x32/set_scno.c1
-rw-r--r--linux/x86_64/set_error.c20
-rw-r--r--linux/x86_64/set_scno.c19
-rw-r--r--linux/xtensa/set_error.c6
-rw-r--r--linux/xtensa/set_scno.c5
61 files changed, 450 insertions, 0 deletions
diff --git a/Makefile.am b/Makefile.am
index ecc35b35a..f801ab27f 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -311,6 +311,8 @@ EXTRA_DIST = \
linux/aarch64/ioctls_arch1.h \
linux/aarch64/ioctls_inc0.h \
linux/aarch64/ioctls_inc1.h \
+ linux/aarch64/set_error.c \
+ linux/aarch64/set_scno.c \
linux/aarch64/signalent1.h \
linux/aarch64/syscallent.h \
linux/aarch64/syscallent1.h \
@@ -325,6 +327,8 @@ EXTRA_DIST = \
linux/alpha/get_syscall_result.c\
linux/alpha/ioctls_arch0.h \
linux/alpha/ioctls_inc0.h \
+ linux/alpha/set_error.c \
+ linux/alpha/set_scno.c \
linux/alpha/signalent.h \
linux/alpha/syscallent.h \
linux/alpha/userent.h \
@@ -334,6 +338,8 @@ EXTRA_DIST = \
linux/arc/get_syscall_args.c \
linux/arc/ioctls_arch0.h \
linux/arc/ioctls_inc0.h \
+ linux/arc/set_error.c \
+ linux/arc/set_scno.c \
linux/arc/syscallent.h \
linux/arch_regs.h \
linux/arch_sigreturn.c \
@@ -345,6 +351,8 @@ EXTRA_DIST = \
linux/arm/get_syscall_args.c \
linux/arm/ioctls_arch0.h \
linux/arm/ioctls_inc0.h \
+ linux/arm/set_error.c \
+ linux/arm/set_scno.c \
linux/arm/syscallent.h \
linux/arm/userent.h \
linux/avr32/arch_regs.c \
@@ -353,6 +361,8 @@ EXTRA_DIST = \
linux/avr32/get_syscall_args.c \
linux/avr32/ioctls_arch0.h \
linux/avr32/ioctls_inc0.h \
+ linux/avr32/set_error.c \
+ linux/avr32/set_scno.c \
linux/avr32/syscallent.h \
linux/avr32/userent.h \
linux/bfin/arch_regs.c \
@@ -362,6 +372,8 @@ EXTRA_DIST = \
linux/bfin/get_syscall_result.c \
linux/bfin/ioctls_arch0.h \
linux/bfin/ioctls_inc0.h \
+ linux/bfin/set_error.c \
+ linux/bfin/set_scno.c \
linux/bfin/syscallent.h \
linux/bfin/userent.h \
linux/crisv10/arch_regs.c \
@@ -370,6 +382,8 @@ EXTRA_DIST = \
linux/crisv10/get_scno.c \
linux/crisv10/get_syscall_args.c \
linux/crisv10/get_syscall_result.c \
+ linux/crisv10/set_error.c \
+ linux/crisv10/set_scno.c \
linux/crisv10/syscallent.h \
linux/crisv10/userent.h \
linux/crisv32/arch_regs.c \
@@ -378,6 +392,8 @@ EXTRA_DIST = \
linux/crisv32/get_scno.c \
linux/crisv32/get_syscall_args.c \
linux/crisv32/get_syscall_result.c \
+ linux/crisv32/set_error.c \
+ linux/crisv32/set_scno.c \
linux/crisv32/syscallent.h \
linux/crisv32/userent.h \
linux/dummy.h \
@@ -392,6 +408,8 @@ EXTRA_DIST = \
linux/hppa/get_syscall_result.c \
linux/hppa/ioctls_arch0.h \
linux/hppa/ioctls_inc0.h \
+ linux/hppa/set_error.c \
+ linux/hppa/set_scno.c \
linux/hppa/signalent.h \
linux/hppa/syscallent.h \
linux/i386/arch_regs.c \
@@ -402,6 +420,8 @@ EXTRA_DIST = \
linux/i386/get_syscall_args.c \
linux/i386/ioctls_arch0.h \
linux/i386/ioctls_inc0.h \
+ linux/i386/set_error.c \
+ linux/i386/set_scno.c \
linux/i386/syscallent.h \
linux/i386/userent.h \
linux/i386/userent0.h \
@@ -414,6 +434,8 @@ EXTRA_DIST = \
linux/ia64/get_syscall_args.c \
linux/ia64/ioctls_arch0.h \
linux/ia64/ioctls_inc0.h \
+ linux/ia64/set_error.c \
+ linux/ia64/set_scno.c \
linux/ia64/syscallent.h \
linux/ia64/userent.h \
linux/inet_diag.h \
@@ -425,6 +447,8 @@ EXTRA_DIST = \
linux/m68k/get_syscall_args.c \
linux/m68k/ioctls_arch0.h \
linux/m68k/ioctls_inc0.h \
+ linux/m68k/set_error.c \
+ linux/m68k/set_scno.c \
linux/m68k/syscallent.h \
linux/m68k/userent.h \
linux/metag/arch_regs.c \
@@ -433,6 +457,8 @@ EXTRA_DIST = \
linux/metag/get_syscall_args.c \
linux/metag/ioctls_arch0.h \
linux/metag/ioctls_inc0.h \
+ linux/metag/set_error.c \
+ linux/metag/set_scno.c \
linux/metag/syscallent.h \
linux/microblaze/arch_regs.c \
linux/microblaze/arch_sigreturn.c \
@@ -442,6 +468,8 @@ EXTRA_DIST = \
linux/microblaze/get_syscall_result.c \
linux/microblaze/ioctls_arch0.h \
linux/microblaze/ioctls_inc0.h \
+ linux/microblaze/set_error.c \
+ linux/microblaze/set_scno.c \
linux/microblaze/syscallent.h \
linux/microblaze/userent.h \
linux/mips/arch_getrval2.c \
@@ -455,6 +483,8 @@ EXTRA_DIST = \
linux/mips/get_syscall_args.c \
linux/mips/ioctls_arch0.h \
linux/mips/ioctls_inc0.h \
+ linux/mips/set_error.c \
+ linux/mips/set_scno.c \
linux/mips/signalent.h \
linux/mips/syscallent-compat.h \
linux/mips/syscallent-n32.h \
@@ -470,6 +500,8 @@ EXTRA_DIST = \
linux/nios2/get_syscall_args.c \
linux/nios2/ioctls_arch0.h \
linux/nios2/ioctls_inc0.h \
+ linux/nios2/set_error.c \
+ linux/nios2/set_scno.c \
linux/nios2/syscallent.h \
linux/or1k/arch_regs.c \
linux/or1k/get_error.c \
@@ -477,6 +509,8 @@ EXTRA_DIST = \
linux/or1k/get_syscall_args.c \
linux/or1k/ioctls_arch0.h \
linux/or1k/ioctls_inc0.h \
+ linux/or1k/set_error.c \
+ linux/or1k/set_scno.c \
linux/or1k/syscallent.h \
linux/or1k/userent.h \
linux/personality.h \
@@ -491,6 +525,8 @@ EXTRA_DIST = \
linux/powerpc/getregs_old.h \
linux/powerpc/ioctls_arch0.h \
linux/powerpc/ioctls_inc0.h \
+ linux/powerpc/set_error.c \
+ linux/powerpc/set_scno.c \
linux/powerpc/syscallent.h \
linux/powerpc/userent.h \
linux/powerpc64/arch_regs.c \
@@ -507,6 +543,8 @@ EXTRA_DIST = \
linux/powerpc64/ioctls_arch1.h \
linux/powerpc64/ioctls_inc0.h \
linux/powerpc64/ioctls_inc1.h \
+ linux/powerpc64/set_error.c \
+ linux/powerpc64/set_scno.c \
linux/powerpc64/signalent1.h \
linux/powerpc64/syscallent.h \
linux/powerpc64/syscallent1.h \
@@ -521,6 +559,8 @@ EXTRA_DIST = \
linux/riscv/ioctls_arch1.h \
linux/riscv/ioctls_inc0.h \
linux/riscv/ioctls_inc1.h \
+ linux/riscv/set_error.c \
+ linux/riscv/set_scno.c \
linux/riscv/signalent1.h \
linux/riscv/syscallent.h \
linux/riscv/syscallent1.h \
@@ -532,6 +572,8 @@ EXTRA_DIST = \
linux/s390/get_syscall_args.c \
linux/s390/ioctls_arch0.h \
linux/s390/ioctls_inc0.h \
+ linux/s390/set_error.c \
+ linux/s390/set_scno.c \
linux/s390/syscallent.h \
linux/s390/userent.h \
linux/s390/userent0.h \
@@ -544,6 +586,8 @@ EXTRA_DIST = \
linux/s390x/get_syscall_args.c \
linux/s390x/ioctls_arch0.h \
linux/s390x/ioctls_inc0.h \
+ linux/s390x/set_error.c \
+ linux/s390x/set_scno.c \
linux/s390x/syscallent.h \
linux/s390x/userent.h \
linux/sh/arch_getrval2.c \
@@ -554,6 +598,8 @@ EXTRA_DIST = \
linux/sh/get_syscall_result.c \
linux/sh/ioctls_arch0.h \
linux/sh/ioctls_inc0.h \
+ linux/sh/set_error.c \
+ linux/sh/set_scno.c \
linux/sh/syscallent.h \
linux/sh/userent.h \
linux/sh/userent0.h \
@@ -565,6 +611,8 @@ EXTRA_DIST = \
linux/sh64/get_syscall_result.c \
linux/sh64/ioctls_arch0.h \
linux/sh64/ioctls_inc0.h \
+ linux/sh64/set_error.c \
+ linux/sh64/set_scno.c \
linux/sh64/syscallent.h \
linux/sh64/userent.h \
linux/signalent.h \
@@ -580,6 +628,8 @@ EXTRA_DIST = \
linux/sparc/get_syscall_args.c \
linux/sparc/ioctls_arch0.h \
linux/sparc/ioctls_inc0.h \
+ linux/sparc/set_error.c \
+ linux/sparc/set_scno.c \
linux/sparc/signalent.h \
linux/sparc/syscallent.h \
linux/sparc/userent.h \
@@ -596,6 +646,8 @@ EXTRA_DIST = \
linux/sparc64/ioctls_arch1.h \
linux/sparc64/ioctls_inc0.h \
linux/sparc64/ioctls_inc1.h \
+ linux/sparc64/set_error.c \
+ linux/sparc64/set_scno.c \
linux/sparc64/signalent.h \
linux/sparc64/signalent1.h \
linux/sparc64/syscallent.h \
@@ -614,6 +666,8 @@ EXTRA_DIST = \
linux/tile/ioctls_arch1.h \
linux/tile/ioctls_inc0.h \
linux/tile/ioctls_inc1.h \
+ linux/tile/set_error.c \
+ linux/tile/set_scno.c \
linux/tile/signalent1.h \
linux/tile/syscallent.h \
linux/tile/syscallent1.h \
@@ -633,6 +687,8 @@ EXTRA_DIST = \
linux/x32/ioctls_arch1.h \
linux/x32/ioctls_inc0.h \
linux/x32/ioctls_inc1.h \
+ linux/x32/set_error.c \
+ linux/x32/set_scno.c \
linux/x32/signalent1.h \
linux/x32/syscallent.h \
linux/x32/syscallent1.h \
@@ -654,6 +710,8 @@ EXTRA_DIST = \
linux/x86_64/ioctls_inc0.h \
linux/x86_64/ioctls_inc1.h \
linux/x86_64/ioctls_inc2.h \
+ linux/x86_64/set_error.c \
+ linux/x86_64/set_scno.c \
linux/x86_64/signalent1.h \
linux/x86_64/signalent2.h \
linux/x86_64/syscallent.h \
@@ -667,6 +725,8 @@ EXTRA_DIST = \
linux/xtensa/get_syscall_result.c \
linux/xtensa/ioctls_arch0.h \
linux/xtensa/ioctls_inc0.h \
+ linux/xtensa/set_error.c \
+ linux/xtensa/set_scno.c \
linux/xtensa/syscallent.h \
linux/xtensa/userent.h \
maint/ioctls_gen.sh \
diff --git a/linux/aarch64/set_error.c b/linux/aarch64/set_error.c
new file mode 100644
index 000000000..f1d3aca89
--- /dev/null
+++ b/linux/aarch64/set_error.c
@@ -0,0 +1,13 @@
+#define arch_set_error arm_set_error
+#include "arm/set_error.c"
+#undef arch_set_error
+
+static int
+arch_set_error(struct tcb *tcp)
+{
+ if (aarch64_io.iov_len == sizeof(arm_regs))
+ return arm_set_error(tcp);
+
+ aarch64_regs.regs[0] = -tcp->u_error;
+ return set_regs(tcp->pid);
+}
diff --git a/linux/aarch64/set_scno.c b/linux/aarch64/set_scno.c
new file mode 100644
index 000000000..70e0a1725
--- /dev/null
+++ b/linux/aarch64/set_scno.c
@@ -0,0 +1,18 @@
+#ifndef NT_ARM_SYSTEM_CALL
+# define NT_ARM_SYSTEM_CALL 0x404
+#endif
+
+static int
+arch_set_scno(struct tcb *tcp, long scno)
+{
+ unsigned int n = (uint16_t) scno;
+ const struct iovec io = {
+ .iov_base = &n,
+ .iov_len = sizeof(n)
+ };
+ int rc = ptrace(PTRACE_SETREGSET, tcp->pid, NT_ARM_SYSTEM_CALL, &io);
+ if (rc && errno != ESRCH)
+ perror_msg("arch_set_scno: NT_ARM_SYSTEM_CALL pid:%d scno:%#x",
+ tcp->pid, n);
+ return rc;
+}
diff --git a/linux/alpha/set_error.c b/linux/alpha/set_error.c
new file mode 100644
index 000000000..e4e38de3b
--- /dev/null
+++ b/linux/alpha/set_error.c
@@ -0,0 +1,6 @@
+static int
+arch_set_error(struct tcb *tcp)
+{
+ alpha_r0 = tcp->u_error;
+ return upoke(tcp->pid, REG_R0, alpha_r0);
+}
diff --git a/linux/alpha/set_scno.c b/linux/alpha/set_scno.c
new file mode 100644
index 000000000..21c603aad
--- /dev/null
+++ b/linux/alpha/set_scno.c
@@ -0,0 +1,5 @@
+static int
+arch_set_scno(struct tcb *tcp, long scno)
+{
+ return upoke(tcp->pid, REG_R0, scno);
+}
diff --git a/linux/arc/set_error.c b/linux/arc/set_error.c
new file mode 100644
index 000000000..3cb0a6b10
--- /dev/null
+++ b/linux/arc/set_error.c
@@ -0,0 +1,6 @@
+static int
+arch_set_error(struct tcb *tcp)
+{
+ arc_regs.scratch.r0 = -tcp->u_error;
+ return set_regs(tcp->pid);
+}
diff --git a/linux/arc/set_scno.c b/linux/arc/set_scno.c
new file mode 100644
index 000000000..afac740e6
--- /dev/null
+++ b/linux/arc/set_scno.c
@@ -0,0 +1,6 @@
+static int
+arch_set_scno(struct tcb *tcp, long scno)
+{
+ arc_regs.scratch.r8 = scno;
+ return set_regs(tcp->pid);
+}
diff --git a/linux/arm/set_error.c b/linux/arm/set_error.c
new file mode 100644
index 000000000..9653d76b9
--- /dev/null
+++ b/linux/arm/set_error.c
@@ -0,0 +1,6 @@
+static int
+arch_set_error(struct tcb *tcp)
+{
+ arm_regs.ARM_r0 = -tcp->u_error;
+ return set_regs(tcp->pid);
+}
diff --git a/linux/arm/set_scno.c b/linux/arm/set_scno.c
new file mode 100644
index 000000000..f99a7fbf4
--- /dev/null
+++ b/linux/arm/set_scno.c
@@ -0,0 +1,14 @@
+#ifndef PTRACE_SET_SYSCALL
+# define PTRACE_SET_SYSCALL 23
+#endif
+
+static int
+arch_set_scno(struct tcb *tcp, long scno)
+{
+ unsigned int n = (uint16_t) scno;
+ int rc = ptrace(PTRACE_SET_SYSCALL, tcp->pid, NULL, (unsigned long) n);
+ if (rc && errno != ESRCH)
+ perror_msg("arch_set_scno: PTRACE_SET_SYSCALL pid:%d scno:%#x",
+ tcp->pid, n);
+ return rc;
+}
diff --git a/linux/avr32/set_error.c b/linux/avr32/set_error.c
new file mode 100644
index 000000000..aeb474a1a
--- /dev/null
+++ b/linux/avr32/set_error.c
@@ -0,0 +1,6 @@
+static int
+arch_set_error(struct tcb *tcp)
+{
+ avr32_regs.r12 = -tcp->u_error;
+ return set_regs(tcp->pid);
+}
diff --git a/linux/avr32/set_scno.c b/linux/avr32/set_scno.c
new file mode 100644
index 000000000..1090d2f36
--- /dev/null
+++ b/linux/avr32/set_scno.c
@@ -0,0 +1,6 @@
+static int
+arch_set_scno(struct tcb *tcp, long scno)
+{
+ avr32_regs.r8 = scno;
+ return set_regs(tcp->pid);
+}
diff --git a/linux/bfin/set_error.c b/linux/bfin/set_error.c
new file mode 100644
index 000000000..daa35268e
--- /dev/null
+++ b/linux/bfin/set_error.c
@@ -0,0 +1,6 @@
+static int
+arch_set_error(struct tcb *tcp)
+{
+ bfin_r0 = -tcp->u_error;
+ return upoke(tcp->pid, PT_R0, bfin_r0);
+}
diff --git a/linux/bfin/set_scno.c b/linux/bfin/set_scno.c
new file mode 100644
index 000000000..235dbb3a2
--- /dev/null
+++ b/linux/bfin/set_scno.c
@@ -0,0 +1,5 @@
+static int
+arch_set_scno(struct tcb *tcp, long scno)
+{
+ return upoke(tcp->pid, PT_ORIG_P0, scno);
+}
diff --git a/linux/crisv10/set_error.c b/linux/crisv10/set_error.c
new file mode 100644
index 000000000..d99ee5f77
--- /dev/null
+++ b/linux/crisv10/set_error.c
@@ -0,0 +1,6 @@
+static int
+arch_set_error(struct tcb *tcp)
+{
+ cris_r10 = -tcp->u_error;
+ return upoke(tcp->pid, 4 * PT_R10, cris_r10);
+}
diff --git a/linux/crisv10/set_scno.c b/linux/crisv10/set_scno.c
new file mode 100644
index 000000000..4ccba5ac3
--- /dev/null
+++ b/linux/crisv10/set_scno.c
@@ -0,0 +1,5 @@
+static int
+arch_set_scno(struct tcb *tcp, long scno)
+{
+ return upoke(tcp->pid, 4 * PT_R9, scno);
+}
diff --git a/linux/crisv32/set_error.c b/linux/crisv32/set_error.c
new file mode 100644
index 000000000..18a5ee8cc
--- /dev/null
+++ b/linux/crisv32/set_error.c
@@ -0,0 +1 @@
+#include "crisv10/set_error.c"
diff --git a/linux/crisv32/set_scno.c b/linux/crisv32/set_scno.c
new file mode 100644
index 000000000..b021adf12
--- /dev/null
+++ b/linux/crisv32/set_scno.c
@@ -0,0 +1 @@
+#include "crisv10/set_scno.c"
diff --git a/linux/hppa/set_error.c b/linux/hppa/set_error.c
new file mode 100644
index 000000000..6d19695e5
--- /dev/null
+++ b/linux/hppa/set_error.c
@@ -0,0 +1,6 @@
+static int
+arch_set_error(struct tcb *tcp)
+{
+ hppa_r28 = -tcp->u_error;
+ return upoke(tcp->pid, PT_GR28, hppa_r28);
+}
diff --git a/linux/hppa/set_scno.c b/linux/hppa/set_scno.c
new file mode 100644
index 000000000..21321a026
--- /dev/null
+++ b/linux/hppa/set_scno.c
@@ -0,0 +1,5 @@
+static int
+arch_set_scno(struct tcb *tcp, long scno)
+{
+ return upoke(tcp->pid, PT_GR20, scno);
+}
diff --git a/linux/i386/set_error.c b/linux/i386/set_error.c
new file mode 100644
index 000000000..fb567d893
--- /dev/null
+++ b/linux/i386/set_error.c
@@ -0,0 +1,10 @@
+static int
+arch_set_error(struct tcb *tcp)
+{
+ i386_regs.eax = -tcp->u_error;
+#ifdef HAVE_GETREGS_OLD
+ return upoke(tcp->pid, 4 * EAX, i386_regs.eax);
+#else
+ return set_regs(tcp->pid);
+#endif
+}
diff --git a/linux/i386/set_scno.c b/linux/i386/set_scno.c
new file mode 100644
index 000000000..1affa3a16
--- /dev/null
+++ b/linux/i386/set_scno.c
@@ -0,0 +1,10 @@
+static int
+arch_set_scno(struct tcb *tcp, long scno)
+{
+#ifdef HAVE_GETREGS_OLD
+ return upoke(tcp->pid, 4 * ORIG_EAX, scno);
+#else
+ i386_regs.orig_eax = scno;
+ return set_regs(tcp->pid);
+#endif
+}
diff --git a/linux/ia64/set_error.c b/linux/ia64/set_error.c
new file mode 100644
index 000000000..4ce79f36f
--- /dev/null
+++ b/linux/ia64/set_error.c
@@ -0,0 +1,11 @@
+static int
+arch_set_error(struct tcb *tcp)
+{
+ if (ia64_ia32mode) {
+ ia64_regs.gr[8] = -tcp->u_error;
+ } else {
+ ia64_regs.gr[8] = tcp->u_error;
+ ia64_regs.gr[10] = -1;
+ }
+ return set_regs(tcp->pid);
+}
diff --git a/linux/ia64/set_scno.c b/linux/ia64/set_scno.c
new file mode 100644
index 000000000..3450f1c35
--- /dev/null
+++ b/linux/ia64/set_scno.c
@@ -0,0 +1,10 @@
+static int
+arch_set_scno(struct tcb *tcp, long scno)
+{
+ if (ia64_ia32mode)
+ ia64_regs.gr[0] = scno;
+ else
+ ia64_regs.gr[15] = scno;
+
+ return set_regs(tcp->pid);
+}
diff --git a/linux/m68k/set_error.c b/linux/m68k/set_error.c
new file mode 100644
index 000000000..7e49bce66
--- /dev/null
+++ b/linux/m68k/set_error.c
@@ -0,0 +1,6 @@
+static int
+arch_set_error(struct tcb *tcp)
+{
+ m68k_regs.d0 = -tcp->u_error;
+ return set_regs(tcp->pid);
+}
diff --git a/linux/m68k/set_scno.c b/linux/m68k/set_scno.c
new file mode 100644
index 000000000..f8753b341
--- /dev/null
+++ b/linux/m68k/set_scno.c
@@ -0,0 +1,6 @@
+static int
+arch_set_scno(struct tcb *tcp, long scno)
+{
+ m68k_regs.orig_d0 = scno;
+ return set_regs(tcp->pid);
+}
diff --git a/linux/metag/set_error.c b/linux/metag/set_error.c
new file mode 100644
index 000000000..97875961d
--- /dev/null
+++ b/linux/metag/set_error.c
@@ -0,0 +1,6 @@
+static int
+arch_set_error(struct tcb *tcp)
+{
+ metag_regs.dx[0][0] = -tcp->u_error;
+ return set_regs(tcp->pid);
+}
diff --git a/linux/metag/set_scno.c b/linux/metag/set_scno.c
new file mode 100644
index 000000000..72198d661
--- /dev/null
+++ b/linux/metag/set_scno.c
@@ -0,0 +1,6 @@
+static int
+arch_set_scno(struct tcb *tcp, long scno)
+{
+ metag_regs.dx[0][1] = scno;
+ return set_regs(tcp->pid);
+}
diff --git a/linux/microblaze/set_error.c b/linux/microblaze/set_error.c
new file mode 100644
index 000000000..98c5419ec
--- /dev/null
+++ b/linux/microblaze/set_error.c
@@ -0,0 +1,6 @@
+static int
+arch_set_error(struct tcb *tcp)
+{
+ microblaze_r3 = -tcp->u_error;
+ return upoke(tcp->pid, 3 * 4, microblaze_r3);
+}
diff --git a/linux/microblaze/set_scno.c b/linux/microblaze/set_scno.c
new file mode 100644
index 000000000..0f7ce9ec7
--- /dev/null
+++ b/linux/microblaze/set_scno.c
@@ -0,0 +1,5 @@
+static int
+arch_set_scno(struct tcb *tcp, long scno)
+{
+ return upoke(tcp->pid, 0, scno);
+}
diff --git a/linux/mips/set_error.c b/linux/mips/set_error.c
new file mode 100644
index 000000000..8c8845f54
--- /dev/null
+++ b/linux/mips/set_error.c
@@ -0,0 +1,7 @@
+static int
+arch_set_error(struct tcb *tcp)
+{
+ mips_REG_V0 = tcp->u_error;
+ mips_REG_A3 = -1;
+ return set_regs(tcp->pid);
+}
diff --git a/linux/mips/set_scno.c b/linux/mips/set_scno.c
new file mode 100644
index 000000000..fc7a63bb2
--- /dev/null
+++ b/linux/mips/set_scno.c
@@ -0,0 +1,6 @@
+static int
+arch_set_scno(struct tcb *tcp, long scno)
+{
+ mips_REG_V0 = scno;
+ return set_regs(tcp->pid);
+}
diff --git a/linux/nios2/set_error.c b/linux/nios2/set_error.c
new file mode 100644
index 000000000..e09b2556f
--- /dev/null
+++ b/linux/nios2/set_error.c
@@ -0,0 +1,7 @@
+static int
+arch_set_error(struct tcb *tcp)
+{
+ nios2_regs.regs[7] = 1;
+ nios2_regs.regs[2] = -tcp->u_error;
+ return set_regs(tcp->pid);
+}
diff --git a/linux/nios2/set_scno.c b/linux/nios2/set_scno.c
new file mode 100644
index 000000000..e8e06bebc
--- /dev/null
+++ b/linux/nios2/set_scno.c
@@ -0,0 +1,6 @@
+static int
+arch_set_scno(struct tcb *tcp, long scno)
+{
+ nios2_regs.regs[2] = scno;
+ return set_regs(tcp->pid);
+}
diff --git a/linux/or1k/set_error.c b/linux/or1k/set_error.c
new file mode 100644
index 000000000..d532679ce
--- /dev/null
+++ b/linux/or1k/set_error.c
@@ -0,0 +1,6 @@
+static int
+arch_set_error(struct tcb *tcp)
+{
+ or1k_regs.gpr[11] = -tcp->u_error;
+ return set_regs(tcp->pid);
+}
diff --git a/linux/or1k/set_scno.c b/linux/or1k/set_scno.c
new file mode 100644
index 000000000..5cf7672a0
--- /dev/null
+++ b/linux/or1k/set_scno.c
@@ -0,0 +1,6 @@
+static int
+arch_set_scno(struct tcb *tcp, long scno)
+{
+ or1k_regs.gpr[11] = scno;
+ return set_regs(tcp->pid);
+}
diff --git a/linux/powerpc/set_error.c b/linux/powerpc/set_error.c
new file mode 100644
index 000000000..fb18f1731
--- /dev/null
+++ b/linux/powerpc/set_error.c
@@ -0,0 +1,10 @@
+static int
+arch_set_error(struct tcb *tcp)
+{
+ ppc_regs.gpr[3] = tcp->u_error;
+#ifdef HAVE_GETREGS_OLD
+ return upoke(tcp->pid, sizeof(long) * (PT_R0 + 3), ppc_regs.gpr[3]);
+#else
+ return set_regs(tcp->pid);
+#endif
+}
diff --git a/linux/powerpc/set_scno.c b/linux/powerpc/set_scno.c
new file mode 100644
index 000000000..9c1acd0a5
--- /dev/null
+++ b/linux/powerpc/set_scno.c
@@ -0,0 +1,10 @@
+static int
+arch_set_scno(struct tcb *tcp, long scno)
+{
+#ifdef HAVE_GETREGS_OLD
+ return upoke(tcp->pid, sizeof(long) * PT_R0, scno);
+#else
+ ppc_regs.gpr[0] = scno;
+ return set_regs(tcp->pid);
+#endif
+}
diff --git a/linux/powerpc64/set_error.c b/linux/powerpc64/set_error.c
new file mode 100644
index 000000000..b8dc768fc
--- /dev/null
+++ b/linux/powerpc64/set_error.c
@@ -0,0 +1 @@
+#include "powerpc/set_error.c"
diff --git a/linux/powerpc64/set_scno.c b/linux/powerpc64/set_scno.c
new file mode 100644
index 000000000..c23bb83e9
--- /dev/null
+++ b/linux/powerpc64/set_scno.c
@@ -0,0 +1 @@
+#include "powerpc/set_scno.c"
diff --git a/linux/riscv/set_error.c b/linux/riscv/set_error.c
new file mode 100644
index 000000000..54fd92550
--- /dev/null
+++ b/linux/riscv/set_error.c
@@ -0,0 +1,6 @@
+static int
+arch_set_error(struct tcb *tcp)
+{
+ riscv_regs.a0 = -tcp->u_error;
+ return set_regs(tcp->pid);
+}
diff --git a/linux/riscv/set_scno.c b/linux/riscv/set_scno.c
new file mode 100644
index 000000000..4ef3d6ef5
--- /dev/null
+++ b/linux/riscv/set_scno.c
@@ -0,0 +1,6 @@
+static int
+arch_set_scno(struct tcb *tcp, long scno)
+{
+ riscv_regs.a7 = scno;
+ return set_regs(tcp->pid);
+}
diff --git a/linux/s390/set_error.c b/linux/s390/set_error.c
new file mode 100644
index 000000000..d691c9a24
--- /dev/null
+++ b/linux/s390/set_error.c
@@ -0,0 +1,6 @@
+static int
+arch_set_error(struct tcb *tcp)
+{
+ s390_regset.gprs[2] = -tcp->u_error;
+ return set_regs(tcp->pid);
+}
diff --git a/linux/s390/set_scno.c b/linux/s390/set_scno.c
new file mode 100644
index 000000000..e21c54098
--- /dev/null
+++ b/linux/s390/set_scno.c
@@ -0,0 +1,6 @@
+static int
+arch_set_scno(struct tcb *tcp, long scno)
+{
+ s390_regset.gprs[2] = scno;
+ return set_regs(tcp->pid);
+}
diff --git a/linux/s390x/set_error.c b/linux/s390x/set_error.c
new file mode 100644
index 000000000..737ddef7a
--- /dev/null
+++ b/linux/s390x/set_error.c
@@ -0,0 +1 @@
+#include "s390/set_error.c"
diff --git a/linux/s390x/set_scno.c b/linux/s390x/set_scno.c
new file mode 100644
index 000000000..9cea4d10b
--- /dev/null
+++ b/linux/s390x/set_scno.c
@@ -0,0 +1 @@
+#include "s390/set_scno.c"
diff --git a/linux/sh/set_error.c b/linux/sh/set_error.c
new file mode 100644
index 000000000..cd646f518
--- /dev/null
+++ b/linux/sh/set_error.c
@@ -0,0 +1,6 @@
+static int
+arch_set_error(struct tcb *tcp)
+{
+ sh_r0 = -tcp->u_error;
+ return upoke(tcp->pid, 4 * REG_REG0, sh_r0);
+}
diff --git a/linux/sh/set_scno.c b/linux/sh/set_scno.c
new file mode 100644
index 000000000..83d603e6c
--- /dev/null
+++ b/linux/sh/set_scno.c
@@ -0,0 +1,5 @@
+static int
+arch_set_scno(struct tcb *tcp, long scno)
+{
+ return upoke(tcp->pid, 4 * (REG_REG0 + 3), scno);
+}
diff --git a/linux/sh64/set_error.c b/linux/sh64/set_error.c
new file mode 100644
index 000000000..79c4229b9
--- /dev/null
+++ b/linux/sh64/set_error.c
@@ -0,0 +1,6 @@
+static int
+arch_set_error(struct tcb *tcp)
+{
+ sh64_r9 = -tcp->u_error;
+ return upoke(tcp->pid, REG_GENERAL(9), sh64_r9);
+}
diff --git a/linux/sh64/set_scno.c b/linux/sh64/set_scno.c
new file mode 100644
index 000000000..212ce2ec5
--- /dev/null
+++ b/linux/sh64/set_scno.c
@@ -0,0 +1,5 @@
+static int
+arch_set_scno(struct tcb *tcp, long scno)
+{
+ return upoke(tcp->pid, REG_SYSCALL, scno);
+}
diff --git a/linux/sparc/set_error.c b/linux/sparc/set_error.c
new file mode 100644
index 000000000..3d757a9e9
--- /dev/null
+++ b/linux/sparc/set_error.c
@@ -0,0 +1,7 @@
+static int
+arch_set_error(struct tcb *tcp)
+{
+ sparc_regs.psr |= PSR_C;
+ sparc_regs.u_regs[U_REG_O0] = tcp->u_error;
+ return set_regs(tcp->pid);
+}
diff --git a/linux/sparc/set_scno.c b/linux/sparc/set_scno.c
new file mode 100644
index 000000000..0f8c4ace1
--- /dev/null
+++ b/linux/sparc/set_scno.c
@@ -0,0 +1,6 @@
+static int
+arch_set_scno(struct tcb *tcp, long scno)
+{
+ sparc_regs.u_regs[U_REG_G1] = scno;
+ return set_regs(tcp->pid);
+}
diff --git a/linux/sparc64/set_error.c b/linux/sparc64/set_error.c
new file mode 100644
index 000000000..54a8b6266
--- /dev/null
+++ b/linux/sparc64/set_error.c
@@ -0,0 +1,7 @@
+static int
+arch_set_error(struct tcb *tcp)
+{
+ sparc_regs.tstate |= 0x1100000000UL;
+ sparc_regs.u_regs[U_REG_O0] = tcp->u_error;
+ return set_regs(tcp->pid);
+}
diff --git a/linux/sparc64/set_scno.c b/linux/sparc64/set_scno.c
new file mode 100644
index 000000000..ae57cdfbd
--- /dev/null
+++ b/linux/sparc64/set_scno.c
@@ -0,0 +1 @@
+#include "sparc/set_scno.c"
diff --git a/linux/tile/set_error.c b/linux/tile/set_error.c
new file mode 100644
index 000000000..ceb9d3a1b
--- /dev/null
+++ b/linux/tile/set_error.c
@@ -0,0 +1,6 @@
+static int
+arch_set_error(struct tcb *tcp)
+{
+ tile_regs.regs[0] = -tcp->u_error;
+ return set_regs(tcp->pid);
+}
diff --git a/linux/tile/set_scno.c b/linux/tile/set_scno.c
new file mode 100644
index 000000000..5ba19638e
--- /dev/null
+++ b/linux/tile/set_scno.c
@@ -0,0 +1,6 @@
+static int
+arch_set_scno(struct tcb *tcp, long scno)
+{
+ tile_regs.regs[10] = scno;
+ return set_regs(tcp->pid);
+}
diff --git a/linux/x32/set_error.c b/linux/x32/set_error.c
new file mode 100644
index 000000000..66a732718
--- /dev/null
+++ b/linux/x32/set_error.c
@@ -0,0 +1 @@
+#include "x86_64/set_error.c"
diff --git a/linux/x32/set_scno.c b/linux/x32/set_scno.c
new file mode 100644
index 000000000..5f7cdb4bc
--- /dev/null
+++ b/linux/x32/set_scno.c
@@ -0,0 +1 @@
+#include "x86_64/set_scno.c"
diff --git a/linux/x86_64/set_error.c b/linux/x86_64/set_error.c
new file mode 100644
index 000000000..1e2d23c70
--- /dev/null
+++ b/linux/x86_64/set_error.c
@@ -0,0 +1,20 @@
+#ifndef HAVE_GETREGS_OLD
+# define arch_set_error i386_set_error
+# include "i386/set_error.c"
+# undef arch_set_error
+#endif /* !HAVE_GETREGS_OLD */
+
+static int
+arch_set_error(struct tcb *tcp)
+{
+#ifdef HAVE_GETREGS_OLD
+ x86_64_regs.rax = - (long long) tcp->u_error;
+ return upoke(tcp->pid, 8 * RAX, x86_64_regs.rax);
+#else
+ if (x86_io.iov_len == sizeof(i386_regs))
+ return i386_set_error(tcp);
+
+ x86_64_regs.rax = - (long long) tcp->u_error;
+ return set_regs(tcp->pid);
+#endif
+}
diff --git a/linux/x86_64/set_scno.c b/linux/x86_64/set_scno.c
new file mode 100644
index 000000000..af1910b96
--- /dev/null
+++ b/linux/x86_64/set_scno.c
@@ -0,0 +1,19 @@
+#ifndef HAVE_GETREGS_OLD
+# define arch_set_scno i386_set_scno
+# include "i386/set_scno.c"
+# undef arch_set_scno
+#endif /* !HAVE_GETREGS_OLD */
+
+static int
+arch_set_scno(struct tcb *tcp, long scno)
+{
+#ifdef HAVE_GETREGS_OLD
+ return upoke(tcp->pid, 8 * ORIG_RAX, scno);
+#else
+ if (x86_io.iov_len == sizeof(i386_regs))
+ return i386_set_scno(tcp, scno);
+
+ x86_64_regs.orig_rax = scno;
+ return set_regs(tcp->pid);
+#endif
+}
diff --git a/linux/xtensa/set_error.c b/linux/xtensa/set_error.c
new file mode 100644
index 000000000..d61b04e90
--- /dev/null
+++ b/linux/xtensa/set_error.c
@@ -0,0 +1,6 @@
+static int
+arch_set_error(struct tcb *tcp)
+{
+ xtensa_a2 = -tcp->u_error;
+ return upoke(tcp->pid, REG_A_BASE + 2, xtensa_a2);
+}
diff --git a/linux/xtensa/set_scno.c b/linux/xtensa/set_scno.c
new file mode 100644
index 000000000..532814f20
--- /dev/null
+++ b/linux/xtensa/set_scno.c
@@ -0,0 +1,5 @@
+static int
+arch_set_scno(struct tcb *tcp, long scno)
+{
+ return upoke(tcp->pid, SYSCALL_NR, scno);
+}