commit: c1dc899d4cdece095925e2391aefce3b0ad3785f Author: Mike Frysinger <vapier <AT> gentoo <DOT> org> AuthorDate: Mon Oct 25 05:58:19 2021 +0000 Commit: Mike Frysinger <vapier <AT> gentoo <DOT> org> CommitDate: Mon Oct 25 05:58:19 2021 +0000 URL: https://gitweb.gentoo.org/proj/sandbox.git/commit/?id=c1dc899d
libsandbox: add sparc personality support This allows tracing of sparc32 in a sparc64 multilib setup. Although it doesn't quite work -- the syscall table needs to be reloaded after the exec commits. We leave that out for now since there isn't actually a sparc32+sparc64 multilib port currently. Bug: https://bugs.gentoo.org/293632 Signed-off-by: Mike Frysinger <vapier <AT> gentoo.org> TODO | 3 ++ configure.ac | 4 +++ libsandbox/trace/linux/sparc.c | 70 ++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 77 insertions(+) diff --git a/TODO b/TODO index 6b3df5a..f48068c 100644 --- a/TODO +++ b/TODO @@ -60,3 +60,6 @@ really only way around this would be to have sandbox set up a named pipe in $T and set the message path to that. then it would poll that for data and take care of writing it to its open stderr. + +sparc32 tracing under sparc64 doesn't work quite right. we need to reload the +syscall table after the exec call finishes. not sure any other port needs this. diff --git a/configure.ac b/configure.ac index fee0e4f..f43923c 100644 --- a/configure.ac +++ b/configure.ac @@ -77,6 +77,10 @@ if test "x$enable_schizo" != "xno" ; then SB_CHECK_SCHIZO([s390x], [-m64]) SB_CHECK_SCHIZO([s390], [-m31]) ;; + sparc*linux*) + SB_CHECK_SCHIZO([sparc64], [-m64]) + SB_CHECK_SCHIZO([sparc], [-m32]) + ;; esac SB_SCHIZO_SETTINGS=${SB_SCHIZO_SETTINGS# } if test "x$enable_schizo" != "xno" ; then diff --git a/libsandbox/trace/linux/sparc.c b/libsandbox/trace/linux/sparc.c index cb1cb54..36d737a 100644 --- a/libsandbox/trace/linux/sparc.c +++ b/libsandbox/trace/linux/sparc.c @@ -13,6 +13,76 @@ #define U_REG_G1 0 #define U_REG_O0 7 +#undef _trace_possible +#define _trace_possible _trace_possible + +#ifdef SB_SCHIZO + +static const struct syscall_entry syscall_table_32[] = { +#ifdef SB_SCHIZO_sparc +#define S(s) { SB_SYS_sparc_##s, SB_NR_##s, #s }, +#include "trace_syscalls_sparc.h" +#undef S +#endif + { SB_NR_UNDEF, SB_NR_UNDEF, NULL }, +}; +static const struct syscall_entry syscall_table_64[] = { +#ifdef SB_SCHIZO_sparc64 +#define S(s) { SB_SYS_sparc64_##s, SB_NR_##s, #s }, +#include "trace_syscalls_sparc64.h" +#undef S +#endif + { SB_NR_UNDEF, SB_NR_UNDEF, NULL }, +}; + +static bool pers_is_32(trace_regs *regs) +{ +#ifdef __arch64__ + /* Sparc does not make it easy to detect 32-bit vs 64-bit. + * Inspect the syscall trap insn to see which one it is. + */ + unsigned long ret = do_ptrace(PTRACE_PEEKTEXT, (void *)regs->tpc, NULL); + return (ret >> 32) == 0x91d02010; +#else + return true; +#endif +} + +static const struct syscall_entry *trace_check_personality(void *vregs) +{ + trace_regs *regs = vregs; + if (pers_is_32(regs)) + return syscall_table_32; + else + return syscall_table_64; +} + +static bool _trace_possible(const void *data) +{ +#ifdef __arch64__ + /* sparc64 can trace sparc32. */ + return true; +#else + /* sparc32 can only trace sparc32 :(. */ + const Elf64_Ehdr *ehdr = data; + return ehdr->e_ident[EI_CLASS] == ELFCLASS32; +#endif +} + +#else + +static bool _trace_possible(const void *data) +{ + const Elf64_Ehdr *ehdr = data; +#ifdef __arch64__ + return ehdr->e_ident[EI_CLASS] == ELFCLASS64; +#else + return ehdr->e_ident[EI_CLASS] == ELFCLASS32; +#endif +} + +#endif + /* Sparc systems have swapped the addr/data args. */ #undef trace_get_regs #undef trace_set_regs
