commit:     9d08c42993a418be6eafa1ffd4abf9e1c60ddd77
Author:     Mike Frysinger <vapier <AT> gentoo <DOT> org>
AuthorDate: Sun Dec 20 06:14:28 2015 +0000
Commit:     Mike Frysinger <vapier <AT> gentoo <DOT> org>
CommitDate: Sun Dec 20 06:14:28 2015 +0000
URL:        https://gitweb.gentoo.org/proj/sandbox.git/commit/?id=9d08c429

libsandbox: new s390/s390x ptrace port

Signed-off-by: Mike Frysinger <vapier <AT> gentoo.org>

 configure.ac                  |  4 ++
 libsandbox/trace/linux/arch.c |  2 +
 libsandbox/trace/linux/s390.c | 95 +++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 101 insertions(+)

diff --git a/configure.ac b/configure.ac
index 64089d7..fd783b7 100644
--- a/configure.ac
+++ b/configure.ac
@@ -80,6 +80,10 @@ if test "x$enable_schizo" != "xno" ; then
                SB_CHECK_SCHIZO([x86], [-m32])
                SB_CHECK_SCHIZO([x32], [-mx32])
                ;;
+       s390*linux*)
+               SB_CHECK_SCHIZO([s390x], [-m64])
+               SB_CHECK_SCHIZO([s390], [-m31])
+               ;;
        esac
        SB_SCHIZO_SETTINGS=${SB_SCHIZO_SETTINGS# }
        if test "x$enable_schizo" != "xno" ; then

diff --git a/libsandbox/trace/linux/arch.c b/libsandbox/trace/linux/arch.c
index 957db3b..53461d6 100644
--- a/libsandbox/trace/linux/arch.c
+++ b/libsandbox/trace/linux/arch.c
@@ -13,6 +13,8 @@
 # include "hppa.c"
 #elif defined(__i386__)
 # include "i386.c"
+#elif defined(__s390__)
+# include "s390.c"
 #elif defined(__sparc__)
 # include "sparc.c"
 #elif defined(__x86_64__)

diff --git a/libsandbox/trace/linux/s390.c b/libsandbox/trace/linux/s390.c
new file mode 100644
index 0000000..acbf894
--- /dev/null
+++ b/libsandbox/trace/linux/s390.c
@@ -0,0 +1,95 @@
+#undef _trace_possible
+#define _trace_possible _trace_possible
+
+#ifdef SB_SCHIZO
+
+static const struct syscall_entry syscall_table_32[] = {
+#ifdef SB_SCHIZO_s390
+#define S(s) { SB_SYS_s390_##s, SB_NR_##s, #s },
+#include "trace_syscalls_s390.h"
+#undef S
+#endif
+       { SB_NR_UNDEF, SB_NR_UNDEF, NULL },
+};
+static const struct syscall_entry syscall_table_64[] = {
+#ifdef SB_SCHIZO_s390x
+#define S(s) { SB_SYS_s390x_##s, SB_NR_##s, #s },
+#include "trace_syscalls_s390x.h"
+#undef S
+#endif
+       { SB_NR_UNDEF, SB_NR_UNDEF, NULL },
+};
+
+static bool pers_is_31(trace_regs *regs)
+{
+       return regs->psw.mask & 0x100000000ul ? false : true;
+}
+
+static const struct syscall_entry *trace_check_personality(void *vregs)
+{
+       trace_regs *regs = vregs;
+       return pers_is_31(regs) ? syscall_table_32 : syscall_table_64;
+}
+
+static bool _trace_possible(const void *data)
+{
+       return true;
+}
+
+#else
+
+static bool _trace_possible(const void *data)
+{
+# ifdef __s390x__
+#  define ELFCLASS ELFCLASS64
+# else
+#  define ELFCLASS ELFCLASS32
+# endif
+       const Elf64_Ehdr *ehdr = data;
+       return (ehdr->e_ident[EI_CLASS] == ELFCLASS) &&
+               (ehdr->e_machine == EM_S390);
+}
+
+#endif
+
+#undef trace_get_regs
+static long trace_get_regs(void *vregs)
+{
+       ptrace_area parea = {
+               /* Most regs we want are at the start (pswmask, pswaddr, and 
gpr0...gpr7,
+                * but the orig_gpr2 is much further along in the area. */
+               .len = PT_ORIGGPR2 + sizeof(long),
+               .kernel_addr = PT_PSWMASK,
+               .process_addr = (uintptr_t)vregs,
+       };
+       do_ptrace(PTRACE_PEEKUSR_AREA, &parea, NULL);
+       return 0;
+}
+
+#undef trace_set_regs
+static long trace_set_regs(void *vregs)
+{
+       ptrace_area parea = {
+               /* Most regs we want are at the start (pswmask, pswaddr, and 
gpr0...gpr7,
+                * but the orig_gpr2 is much further along in the area. */
+               .len = PT_ORIGGPR2 + sizeof(long),
+               .kernel_addr = PT_PSWMASK,
+               .process_addr = (uintptr_t)vregs,
+       };
+       do_ptrace(PTRACE_POKEUSR_AREA, &parea, NULL);
+       return 0;
+}
+
+#define trace_reg_sysnum gprs[2]
+#define trace_reg_ret gprs[2]
+
+static unsigned long trace_arg(void *vregs, int num)
+{
+       trace_regs *regs = vregs;
+       if (num == 1)
+               return regs->orig_gpr2;
+       else if (num < 7)
+               return regs->gprs[2 + num - 1];
+       else
+               return -1;
+}

Reply via email to