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.
Reviewed-by: Max Filippov <jcmvb...@gmail.com> Reviewed-by: Philippe Mathieu-Daudé <f4...@amsat.org> Reviewed-by: Peter Maydell <peter.mayd...@linaro.org> Signed-off-by: Richard Henderson <richard.hender...@linaro.org> --- linux-user/signal-common.h | 6 ++++++ linux-user/elfload.c | 18 ++++++++++++++++++ linux-user/signal.c | 3 +++ 3 files changed, 27 insertions(+) diff --git a/linux-user/signal-common.h b/linux-user/signal-common.h index 79511becb4..7457f8025c 100644 --- a/linux-user/signal-common.h +++ b/linux-user/signal-common.h @@ -20,6 +20,12 @@ #ifndef SIGNAL_COMMON_H #define SIGNAL_COMMON_H +/* Fallback addresses into sigtramp page. */ +extern abi_ulong default_sigreturn; +extern abi_ulong default_rt_sigreturn; + +void setup_sigtramp(abi_ulong tramp_page); + int on_sig_stack(unsigned long sp); int sas_ss_flags(unsigned long sp); abi_ulong target_sigsp(abi_ulong sp, struct target_sigaction *ka); diff --git a/linux-user/elfload.c b/linux-user/elfload.c index 5f9e2141ad..459a26ef1d 100644 --- a/linux-user/elfload.c +++ b/linux-user/elfload.c @@ -7,6 +7,7 @@ #include "qemu.h" #include "user-internals.h" +#include "signal-common.h" #include "loader.h" #include "user-mmap.h" #include "disas/disas.h" @@ -17,6 +18,7 @@ #include "qemu/units.h" #include "qemu/selfmap.h" #include "qapi/error.h" +#include "target_signal.h" #ifdef _ARCH_PPC64 #undef ARCH_DLINFO @@ -28,6 +30,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 */ @@ -3249,6 +3255,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 2038216455..14d8fdfde1 100644 --- a/linux-user/signal.c +++ b/linux-user/signal.c @@ -35,6 +35,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