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; +}