Allocate a page to hold the signal trampoline(s). Invoke a guest-specific hook to fill in the contents of the page before marking it read-execute again.
Signed-off-by: Richard Henderson <richard.hender...@linaro.org> --- linux-user/qemu.h | 7 +++++++ linux-user/elfload.c | 17 +++++++++++++++++ linux-user/signal.c | 3 +++ 3 files changed, 27 insertions(+) diff --git a/linux-user/qemu.h b/linux-user/qemu.h index 3b0b6b75fe..9e5e2aa499 100644 --- a/linux-user/qemu.h +++ b/linux-user/qemu.h @@ -437,6 +437,13 @@ abi_long do_sigaltstack(abi_ulong uss_addr, abi_ulong uoss_addr, int do_sigprocmask(int how, const sigset_t *set, sigset_t *oldset); abi_long do_swapcontext(CPUArchState *env, abi_ulong uold_ctx, abi_ulong unew_ctx, abi_long ctx_size); + +/* Fallback addresses into sigtramp page. */ +extern abi_ulong default_sigreturn; +extern abi_ulong default_rt_sigreturn; + +void setup_sigtramp(abi_ulong tramp_page); + /** * block_signals: block all signals while handling this guest syscall * diff --git a/linux-user/elfload.c b/linux-user/elfload.c index 17ab06f612..7bc67ac9cb 100644 --- a/linux-user/elfload.c +++ b/linux-user/elfload.c @@ -14,6 +14,7 @@ #include "qemu/units.h" #include "qemu/selfmap.h" #include "qapi/error.h" +#include "target_signal.h" #ifdef _ARCH_PPC64 #undef ARCH_DLINFO @@ -25,6 +26,10 @@ #undef ELF_ARCH #endif +#ifndef TARGET_ARCH_HAS_SIGTRAMP_PAGE +#define TARGET_ARCH_HAS_SIGTRAMP_PAGE 0 +#endif + #define ELF_OSABI ELFOSABI_SYSV /* from personality.h */ @@ -3232,6 +3237,18 @@ int load_elf_binary(struct linux_binprm *bprm, struct image_info *info) #endif } + /* + * TODO: load a vdso, which would also contain the signal trampolines. + * Otherwise, allocate a private page to hold them. + */ + if (TARGET_ARCH_HAS_SIGTRAMP_PAGE) { + abi_ulong tramp_page = target_mmap(0, TARGET_PAGE_SIZE, + PROT_READ | PROT_WRITE, + MAP_PRIVATE | MAP_ANON, -1, 0); + setup_sigtramp(tramp_page); + target_mprotect(tramp_page, TARGET_PAGE_SIZE, PROT_READ | PROT_EXEC); + } + bprm->p = create_elf_tables(bprm->p, bprm->argc, bprm->envc, &elf_ex, info, (elf_interpreter ? &interp_info : NULL)); info->start_stack = bprm->p; diff --git a/linux-user/signal.c b/linux-user/signal.c index 9016896dcd..2f19cc0bf6 100644 --- a/linux-user/signal.c +++ b/linux-user/signal.c @@ -30,6 +30,9 @@ static struct target_sigaction sigact_table[TARGET_NSIG]; static void host_signal_handler(int host_signum, siginfo_t *info, void *puc); +/* Fallback addresses into sigtramp page. */ +abi_ulong default_sigreturn; +abi_ulong default_rt_sigreturn; /* * System includes define _NSIG as SIGRTMAX + 1, -- 2.25.1