Merge remote-tracking branch 'remotes/vivier/tags/linux-user-for-6.2-pull-request' into staging

Pull request linux-user 20211004

Move signal trampolines to new page

# gpg: Signature made Mon 04 Oct 2021 12:43:53 AM PDT
# gpg:                using RSA key CD2F75DDC8E3A4DC2E4F5173F30C38BD3F2FBE3C
# gpg:                issuer "laurent@vivier.eu"
# gpg: Good signature from "Laurent Vivier <lvivier@redhat.com>" [full]
# gpg:                 aka "Laurent Vivier <laurent@vivier.eu>" [full]
# gpg:                 aka "Laurent Vivier (Red Hat) <lvivier@redhat.com>" [full]

* remotes/vivier/tags/linux-user-for-6.2-pull-request: (26 commits)
  tests/tcg/multiarch: Re-enable signals test for most guests
  linux-user: Remove default for TARGET_ARCH_HAS_SIGTRAMP_PAGE
  linux-user/xtensa: Implement setup_sigtramp
  linux-user/sparc: Implement setup_sigtramp
  linux-user/sh4: Implement setup_sigtramp
  linux-user/s390x: Implement setup_sigtramp
  linux-user/riscv: Implement setup_sigtramp
  linux-user/ppc: Implement setup_sigtramp
  linux-user/ppc: Simplify encode_trampoline
  linux-user/openrisc: Implement setup_sigtramp
  linux-user/nios2: Document non-use of setup_sigtramp
  linux-user/mips: Implement setup_sigtramp
  linux-user/mips: Tidy install_sigtramp
  linux-user/microblaze: Implement setup_sigtramp
  linux-user/m68k: Implement setup_sigtramp
  linux-user/x86_64: Raise SIGSEGV if SA_RESTORER not set
  linux-user/i386: Implement setup_sigtramp
  linux-user/hppa: Document non-use of setup_sigtramp
  linux-user/hexagon: Implement setup_sigtramp
  linux-user/cris: Implement setup_sigtramp
  ...

Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
This commit is contained in:
Richard Henderson
2021-10-04 14:21:39 -07:00
43 changed files with 613 additions and 604 deletions
+21 -13
View File
@@ -109,7 +109,6 @@ struct target_rt_sigframe {
struct target_rt_frame_record {
uint64_t fp;
uint64_t lr;
uint32_t tramp[2];
};
static void target_setup_general_frame(struct target_rt_sigframe *sf,
@@ -461,9 +460,9 @@ static void target_setup_frame(int usig, struct target_sigaction *ka,
layout.total_size = MAX(layout.total_size,
sizeof(struct target_rt_sigframe));
/* Reserve space for the return code. On a real system this would
* be within the VDSO. So, despite the name this is not a "real"
* record within the frame.
/*
* Reserve space for the standard frame unwind pair: fp, lr.
* Despite the name this is not a "real" record within the frame.
*/
fr_ofs = layout.total_size;
layout.total_size += sizeof(struct target_rt_frame_record);
@@ -496,15 +495,7 @@ static void target_setup_frame(int usig, struct target_sigaction *ka,
if (ka->sa_flags & TARGET_SA_RESTORER) {
return_addr = ka->sa_restorer;
} else {
/*
* mov x8,#__NR_rt_sigreturn; svc #0
* Since these are instructions they need to be put as little-endian
* regardless of target default or current CPU endianness.
*/
__put_user_e(0xd2801168, &fr->tramp[0], le);
__put_user_e(0xd4000001, &fr->tramp[1], le);
return_addr = frame_addr + fr_ofs
+ offsetof(struct target_rt_frame_record, tramp);
return_addr = default_rt_sigreturn;
}
env->xregs[0] = usig;
env->xregs[29] = frame_addr + fr_ofs;
@@ -577,3 +568,20 @@ long do_sigreturn(CPUARMState *env)
{
return do_rt_sigreturn(env);
}
void setup_sigtramp(abi_ulong sigtramp_page)
{
uint32_t *tramp = lock_user(VERIFY_WRITE, sigtramp_page, 8, 0);
assert(tramp != NULL);
/*
* mov x8,#__NR_rt_sigreturn; svc #0
* Since these are instructions they need to be put as little-endian
* regardless of target default or current CPU endianness.
*/
__put_user_e(0xd2801168, &tramp[0], le);
__put_user_e(0xd4000001, &tramp[1], le);
default_rt_sigreturn = sigtramp_page;
unlock_user(tramp, sigtramp_page, 8);
}
+2
View File
@@ -25,4 +25,6 @@ typedef struct target_sigaltstack {
#define TARGET_SEGV_MTESERR 9 /* Synchronous ARM MTE exception */
#define TARGET_ARCH_HAS_SETUP_FRAME
#define TARGET_ARCH_HAS_SIGTRAMP_PAGE 1
#endif /* AARCH64_TARGET_SIGNAL_H */
+20 -14
View File
@@ -55,13 +55,11 @@ struct target_ucontext {
struct target_sigframe {
struct target_sigcontext sc;
unsigned int retcode[3];
};
struct target_rt_sigframe {
target_siginfo_t info;
struct target_ucontext uc;
unsigned int retcode[3];
};
#define INSN_MOV_R30_R16 0x47fe0410
@@ -142,12 +140,7 @@ void setup_frame(int sig, struct target_sigaction *ka,
if (ka->ka_restorer) {
r26 = ka->ka_restorer;
} else {
__put_user(INSN_MOV_R30_R16, &frame->retcode[0]);
__put_user(INSN_LDI_R0 + TARGET_NR_sigreturn,
&frame->retcode[1]);
__put_user(INSN_CALLSYS, &frame->retcode[2]);
/* imb() */
r26 = frame_addr + offsetof(struct target_sigframe, retcode);
r26 = default_sigreturn;
}
unlock_user_struct(frame, frame_addr, 1);
@@ -196,12 +189,7 @@ void setup_rt_frame(int sig, struct target_sigaction *ka,
if (ka->ka_restorer) {
r26 = ka->ka_restorer;
} else {
__put_user(INSN_MOV_R30_R16, &frame->retcode[0]);
__put_user(INSN_LDI_R0 + TARGET_NR_rt_sigreturn,
&frame->retcode[1]);
__put_user(INSN_CALLSYS, &frame->retcode[2]);
/* imb(); */
r26 = frame_addr + offsetof(struct target_rt_sigframe, retcode);
r26 = default_rt_sigreturn;
}
if (err) {
@@ -269,3 +257,21 @@ badframe:
force_sig(TARGET_SIGSEGV);
return -TARGET_QEMU_ESIGRETURN;
}
void setup_sigtramp(abi_ulong sigtramp_page)
{
uint32_t *tramp = lock_user(VERIFY_WRITE, sigtramp_page, 6 * 4, 0);
assert(tramp != NULL);
default_sigreturn = sigtramp_page;
__put_user(INSN_MOV_R30_R16, &tramp[0]);
__put_user(INSN_LDI_R0 + TARGET_NR_sigreturn, &tramp[1]);
__put_user(INSN_CALLSYS, &tramp[2]);
default_rt_sigreturn = sigtramp_page + 3 * 4;
__put_user(INSN_MOV_R30_R16, &tramp[3]);
__put_user(INSN_LDI_R0 + TARGET_NR_rt_sigreturn, &tramp[4]);
__put_user(INSN_CALLSYS, &tramp[5]);
unlock_user(tramp, sigtramp_page, 6 * 4);
}
+1
View File
@@ -93,6 +93,7 @@ typedef struct target_sigaltstack {
#define TARGET_ARCH_HAS_SETUP_FRAME
#define TARGET_ARCH_HAS_KA_RESTORER
#define TARGET_ARCH_HAS_SIGTRAMP_PAGE 1
/* bit-flags */
#define TARGET_SS_AUTODISARM (1U << 31) /* disable sas during sighandling */
+190 -390
View File
File diff suppressed because it is too large Load Diff
+2
View File
@@ -22,4 +22,6 @@ typedef struct target_sigaltstack {
#include "../generic/signal.h"
#define TARGET_ARCH_HAS_SETUP_FRAME
#define TARGET_ARCH_HAS_SIGTRAMP_PAGE 1
#endif /* ARM_TARGET_SIGNAL_H */
+21 -8
View File
@@ -97,6 +97,14 @@ static abi_ulong get_sigframe(CPUCRISState *env, int framesize)
return sp - framesize;
}
static void setup_sigreturn(uint16_t *retcode)
{
/* This is movu.w __NR_sigreturn, r9; break 13; */
__put_user(0x9c5f, retcode + 0);
__put_user(TARGET_NR_sigreturn, retcode + 1);
__put_user(0xe93d, retcode + 2);
}
void setup_frame(int sig, struct target_sigaction *ka,
target_sigset_t *set, CPUCRISState *env)
{
@@ -112,14 +120,8 @@ void setup_frame(int sig, struct target_sigaction *ka,
/*
* The CRIS signal return trampoline. A real linux/CRIS kernel doesn't
* use this trampoline anymore but it sets it up for GDB.
* In QEMU, using the trampoline simplifies things a bit so we use it.
*
* This is movu.w __NR_sigreturn, r9; break 13;
*/
__put_user(0x9c5f, frame->retcode+0);
__put_user(TARGET_NR_sigreturn,
frame->retcode + 1);
__put_user(0xe93d, frame->retcode + 2);
setup_sigreturn(frame->retcode);
/* Save the mask. */
__put_user(set->sig[0], &frame->sc.oldmask);
@@ -135,7 +137,7 @@ void setup_frame(int sig, struct target_sigaction *ka,
env->regs[10] = sig;
env->pc = (unsigned long) ka->_sa_handler;
/* Link SRP so the guest returns through the trampoline. */
env->pregs[PR_SRP] = frame_addr + offsetof(typeof(*frame), retcode);
env->pregs[PR_SRP] = default_sigreturn;
unlock_user_struct(frame, frame_addr, 1);
return;
@@ -187,3 +189,14 @@ long do_rt_sigreturn(CPUCRISState *env)
qemu_log_mask(LOG_UNIMP, "do_rt_sigreturn: not implemented\n");
return -TARGET_ENOSYS;
}
void setup_sigtramp(abi_ulong sigtramp_page)
{
uint16_t *tramp = lock_user(VERIFY_WRITE, sigtramp_page, 6, 0);
assert(tramp != NULL);
default_sigreturn = sigtramp_page;
setup_sigreturn(tramp);
unlock_user(tramp, sigtramp_page, 6);
}
+2
View File
@@ -22,4 +22,6 @@ typedef struct target_sigaltstack {
#include "../generic/signal.h"
#define TARGET_ARCH_HAS_SETUP_FRAME
#define TARGET_ARCH_HAS_SIGTRAMP_PAGE 1
#endif /* CRIS_TARGET_SIGNAL_H */
+14
View File
@@ -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
@@ -3249,6 +3251,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;
+17 -2
View File
@@ -162,6 +162,11 @@ void setup_rt_frame(int sig, struct target_sigaction *ka,
setup_ucontext(&frame->uc, env, set);
tswap_siginfo(&frame->info, info);
/*
* The on-stack signal trampoline is no longer executed;
* however, the libgcc signal frame unwinding code checks
* for the presence of these two numeric magic values.
*/
install_sigtramp(frame->tramp);
env->gpr[HEX_REG_PC] = ka->_sa_handler;
@@ -171,8 +176,7 @@ void setup_rt_frame(int sig, struct target_sigaction *ka,
frame_addr + offsetof(struct target_rt_sigframe, info);
env->gpr[HEX_REG_R02] =
frame_addr + offsetof(struct target_rt_sigframe, uc);
env->gpr[HEX_REG_LR] =
frame_addr + offsetof(struct target_rt_sigframe, tramp);
env->gpr[HEX_REG_LR] = default_rt_sigreturn;
return;
@@ -271,3 +275,14 @@ badframe:
force_sig(TARGET_SIGSEGV);
return 0;
}
void setup_sigtramp(abi_ulong sigtramp_page)
{
uint32_t *tramp = lock_user(VERIFY_WRITE, sigtramp_page, 4 * 2, 0);
assert(tramp != NULL);
default_rt_sigreturn = sigtramp_page;
install_sigtramp(tramp);
unlock_user(tramp, sigtramp_page, 4 * 2);
}
+2
View File
@@ -31,4 +31,6 @@ typedef struct target_sigaltstack {
#include "../generic/signal.h"
#define TARGET_ARCH_HAS_SIGTRAMP_PAGE 1
#endif /* TARGET_SIGNAL_H */
+14
View File
@@ -71,4 +71,18 @@ typedef struct target_sigaltstack {
/* mask for all SS_xxx flags */
#define TARGET_SS_FLAG_BITS TARGET_SS_AUTODISARM
/*
* We cannot use a bare sigtramp page for hppa-linux.
*
* Unlike other guests where we use the instructions at PC to validate
* an offset from SP, the hppa libgcc signal frame fallback unwinding uses
* the PC address itself to find the frame. This is due to the fact that
* the hppa grows the stack upward, and the frame is of unknown size.
*
* TODO: We should be able to use a VDSO to address this, by providing
* proper unwind info for the sigtramp code, at which point the fallback
* unwinder will not be used.
*/
#define TARGET_ARCH_HAS_SIGTRAMP_PAGE 0
#endif /* HPPA_TARGET_SIGNAL_H */
+42 -23
View File
@@ -310,6 +310,22 @@ get_sigframe(struct target_sigaction *ka, CPUX86State *env, size_t frame_size)
}
#ifndef TARGET_X86_64
static void install_sigtramp(void *tramp)
{
/* This is popl %eax ; movl $syscall,%eax ; int $0x80 */
__put_user(0xb858, (uint16_t *)(tramp + 0));
__put_user(TARGET_NR_sigreturn, (int32_t *)(tramp + 2));
__put_user(0x80cd, (uint16_t *)(tramp + 6));
}
static void install_rt_sigtramp(void *tramp)
{
/* This is movl $syscall,%eax ; int $0x80 */
__put_user(0xb8, (uint8_t *)(tramp + 0));
__put_user(TARGET_NR_rt_sigreturn, (int32_t *)(tramp + 1));
__put_user(0x80cd, (uint16_t *)(tramp + 5));
}
/* compare linux/arch/i386/kernel/signal.c:setup_frame() */
void setup_frame(int sig, struct target_sigaction *ka,
target_sigset_t *set, CPUX86State *env)
@@ -338,16 +354,9 @@ void setup_frame(int sig, struct target_sigaction *ka,
if (ka->sa_flags & TARGET_SA_RESTORER) {
__put_user(ka->sa_restorer, &frame->pretcode);
} else {
uint16_t val16;
abi_ulong retcode_addr;
retcode_addr = frame_addr + offsetof(struct sigframe, retcode);
__put_user(retcode_addr, &frame->pretcode);
/* This is popl %eax ; movl $,%eax ; int $0x80 */
val16 = 0xb858;
__put_user(val16, (uint16_t *)(frame->retcode+0));
__put_user(TARGET_NR_sigreturn, (int *)(frame->retcode+2));
val16 = 0x80cd;
__put_user(val16, (uint16_t *)(frame->retcode+6));
/* This is no longer used, but is retained for ABI compatibility. */
install_sigtramp(frame->retcode);
__put_user(default_sigreturn, &frame->pretcode);
}
/* Set up registers for signal handler */
@@ -412,24 +421,18 @@ void setup_rt_frame(int sig, struct target_sigaction *ka,
/* Set up to return from userspace. If provided, use a stub
already in userspace. */
#ifndef TARGET_X86_64
if (ka->sa_flags & TARGET_SA_RESTORER) {
__put_user(ka->sa_restorer, &frame->pretcode);
} else {
uint16_t val16;
addr = frame_addr + offsetof(struct rt_sigframe, retcode);
__put_user(addr, &frame->pretcode);
/* This is movl $,%eax ; int $0x80 */
__put_user(0xb8, (char *)(frame->retcode+0));
__put_user(TARGET_NR_rt_sigreturn, (int *)(frame->retcode+1));
val16 = 0x80cd;
__put_user(val16, (uint16_t *)(frame->retcode+5));
}
#ifdef TARGET_X86_64
/* For x86_64, SA_RESTORER is required ABI. */
goto give_sigsegv;
#else
/* XXX: Would be slightly better to return -EFAULT here if test fails
assert(ka->sa_flags & TARGET_SA_RESTORER); */
__put_user(ka->sa_restorer, &frame->pretcode);
/* This is no longer used, but is retained for ABI compatibility. */
install_rt_sigtramp(frame->retcode);
__put_user(default_rt_sigreturn, &frame->pretcode);
#endif
}
/* Set up registers for signal handler */
env->regs[R_ESP] = frame_addr;
@@ -592,3 +595,19 @@ badframe:
force_sig(TARGET_SIGSEGV);
return -TARGET_QEMU_ESIGRETURN;
}
#ifndef TARGET_X86_64
void setup_sigtramp(abi_ulong sigtramp_page)
{
uint16_t *tramp = lock_user(VERIFY_WRITE, sigtramp_page, 2 * 8, 0);
assert(tramp != NULL);
default_sigreturn = sigtramp_page;
install_sigtramp(tramp);
default_rt_sigreturn = sigtramp_page + 8;
install_rt_sigtramp(tramp + 8);
unlock_user(tramp, sigtramp_page, 2 * 8);
}
#endif
+2
View File
@@ -22,4 +22,6 @@ typedef struct target_sigaltstack {
#include "../generic/signal.h"
#define TARGET_ARCH_HAS_SETUP_FRAME
#define TARGET_ARCH_HAS_SIGTRAMP_PAGE 1
#endif /* I386_TARGET_SIGNAL_H */
+22 -25
View File
@@ -39,7 +39,6 @@ struct target_sigframe
int sig;
int code;
abi_ulong psc;
char retcode[8];
abi_ulong extramask[TARGET_NSIG_WORDS-1];
struct target_sigcontext sc;
};
@@ -76,7 +75,6 @@ struct target_rt_sigframe
int sig;
abi_ulong pinfo;
abi_ulong puc;
char retcode[8];
struct target_siginfo info;
struct target_ucontext uc;
};
@@ -130,7 +128,6 @@ void setup_frame(int sig, struct target_sigaction *ka,
{
struct target_sigframe *frame;
abi_ulong frame_addr;
abi_ulong retcode_addr;
abi_ulong sc_addr;
int i;
@@ -152,16 +149,7 @@ void setup_frame(int sig, struct target_sigaction *ka,
}
/* Set up to return from userspace. */
retcode_addr = frame_addr + offsetof(struct target_sigframe, retcode);
__put_user(retcode_addr, &frame->pretcode);
/* moveq #,d0; trap #0 */
__put_user(0x70004e40 + (TARGET_NR_sigreturn << 16),
(uint32_t *)(frame->retcode));
/* Set up to return from userspace */
__put_user(default_sigreturn, &frame->pretcode);
env->aregs[7] = frame_addr;
env->pc = ka->_sa_handler;
@@ -288,7 +276,6 @@ void setup_rt_frame(int sig, struct target_sigaction *ka,
{
struct target_rt_sigframe *frame;
abi_ulong frame_addr;
abi_ulong retcode_addr;
abi_ulong info_addr;
abi_ulong uc_addr;
int err = 0;
@@ -325,17 +312,7 @@ void setup_rt_frame(int sig, struct target_sigaction *ka,
}
/* Set up to return from userspace. */
retcode_addr = frame_addr + offsetof(struct target_sigframe, retcode);
__put_user(retcode_addr, &frame->pretcode);
/* moveq #,d0; notb d0; trap #0 */
__put_user(0x70004600 + ((TARGET_NR_rt_sigreturn ^ 0xff) << 16),
(uint32_t *)(frame->retcode + 0));
__put_user(0x4e40, (uint16_t *)(frame->retcode + 4));
/* Set up to return from userspace */
__put_user(default_rt_sigreturn, &frame->pretcode);
env->aregs[7] = frame_addr;
env->pc = ka->_sa_handler;
@@ -411,3 +388,23 @@ badframe:
force_sig(TARGET_SIGSEGV);
return -TARGET_QEMU_ESIGRETURN;
}
void setup_sigtramp(abi_ulong sigtramp_page)
{
void *tramp = lock_user(VERIFY_WRITE, sigtramp_page, 4 + 6, 0);
assert(tramp != NULL);
default_sigreturn = sigtramp_page;
/* moveq #,d0; trap #0 */
__put_user(0x70004e40 + (TARGET_NR_sigreturn << 16), (uint32_t *)tramp);
default_rt_sigreturn = sigtramp_page + 4;
/* moveq #,d0; notb d0; trap #0 */
__put_user(0x70004600 + ((TARGET_NR_rt_sigreturn ^ 0xff) << 16),
(uint32_t *)(tramp + 4));
__put_user(0x4e40, (uint16_t *)(tramp + 8));
unlock_user(tramp, sigtramp_page, 4 + 6);
}
+2
View File
@@ -22,4 +22,6 @@ typedef struct target_sigaltstack {
#include "../generic/signal.h"
#define TARGET_ARCH_HAS_SETUP_FRAME
#define TARGET_ARCH_HAS_SIGTRAMP_PAGE 1
#endif /* M68K_TARGET_SIGNAL_H */
+17 -7
View File
@@ -161,17 +161,11 @@ void setup_rt_frame(int sig, struct target_sigaction *ka,
/* Kernel does not use SA_RESTORER. */
/* addi r12, r0, __NR_sigreturn */
__put_user(0x31800000U | TARGET_NR_rt_sigreturn, frame->tramp + 0);
/* brki r14, 0x8 */
__put_user(0xb9cc0008U, frame->tramp + 1);
/*
* Return from sighandler will jump to the tramp.
* Negative 8 offset because return is rtsd r15, 8
*/
env->regs[15] =
frame_addr + offsetof(struct target_rt_sigframe, tramp) - 8;
env->regs[15] = default_rt_sigreturn - 8;
/* Set up registers for signal handler */
env->regs[1] = frame_addr;
@@ -220,3 +214,19 @@ long do_rt_sigreturn(CPUMBState *env)
force_sig(TARGET_SIGSEGV);
return -TARGET_QEMU_ESIGRETURN;
}
void setup_sigtramp(abi_ulong sigtramp_page)
{
uint32_t *tramp = lock_user(VERIFY_WRITE, sigtramp_page, 8, 0);
assert(tramp != NULL);
/*
* addi r12, r0, __NR_rt_sigreturn
* brki r14, 0x8
*/
__put_user(0x31800000U | TARGET_NR_rt_sigreturn, tramp);
__put_user(0xb9cc0008U, tramp + 1);
default_rt_sigreturn = sigtramp_page;
unlock_user(tramp, sigtramp_page, 8);
}
+2
View File
@@ -21,4 +21,6 @@ typedef struct target_sigaltstack {
#include "../generic/signal.h"
#define TARGET_ARCH_HAS_SIGTRAMP_PAGE 1
#endif /* MICROBLAZE_TARGET_SIGNAL_H */
+25 -14
View File
@@ -87,10 +87,8 @@ struct target_rt_sigframe {
};
/* Install trampoline to jump back from signal handler */
static inline int install_sigtramp(unsigned int *tramp, unsigned int syscall)
static void install_sigtramp(uint32_t *tramp, unsigned int syscall)
{
int err = 0;
/*
* Set up the return code ...
*
@@ -100,7 +98,6 @@ static inline int install_sigtramp(unsigned int *tramp, unsigned int syscall)
__put_user(0x24020000 + syscall, tramp + 0);
__put_user(0x0000000c , tramp + 1);
return err;
}
static inline void setup_sigcontext(CPUMIPSState *regs,
@@ -212,8 +209,6 @@ void setup_frame(int sig, struct target_sigaction * ka,
goto give_sigsegv;
}
install_sigtramp(frame->sf_code, TARGET_NR_sigreturn);
setup_sigcontext(regs, &frame->sf_sc);
for(i = 0; i < TARGET_NSIG_WORDS; i++) {
@@ -234,7 +229,7 @@ void setup_frame(int sig, struct target_sigaction * ka,
regs->active_tc.gpr[ 5] = 0;
regs->active_tc.gpr[ 6] = frame_addr + offsetof(struct sigframe, sf_sc);
regs->active_tc.gpr[29] = frame_addr;
regs->active_tc.gpr[31] = frame_addr + offsetof(struct sigframe, sf_code);
regs->active_tc.gpr[31] = default_sigreturn;
/* The original kernel code sets CP0_EPC to the handler
* since it returns to userland using eret
* we cannot do this here, and we must set PC directly */
@@ -308,8 +303,6 @@ void setup_rt_frame(int sig, struct target_sigaction *ka,
goto give_sigsegv;
}
install_sigtramp(frame->rs_code, TARGET_NR_rt_sigreturn);
tswap_siginfo(&frame->rs_info, info);
__put_user(0, &frame->rs_uc.tuc_flags);
@@ -338,11 +331,13 @@ void setup_rt_frame(int sig, struct target_sigaction *ka,
env->active_tc.gpr[ 6] = frame_addr
+ offsetof(struct target_rt_sigframe, rs_uc);
env->active_tc.gpr[29] = frame_addr;
env->active_tc.gpr[31] = frame_addr
+ offsetof(struct target_rt_sigframe, rs_code);
/* The original kernel code sets CP0_EPC to the handler
* since it returns to userland using eret
* we cannot do this here, and we must set PC directly */
env->active_tc.gpr[31] = default_rt_sigreturn;
/*
* The original kernel code sets CP0_EPC to the handler
* since it returns to userland using eret
* we cannot do this here, and we must set PC directly
*/
env->active_tc.PC = env->active_tc.gpr[25] = ka->_sa_handler;
mips_set_hflags_isa_mode_from_pc(env);
unlock_user_struct(frame, frame_addr, 1);
@@ -382,3 +377,19 @@ badframe:
force_sig(TARGET_SIGSEGV);
return -TARGET_QEMU_ESIGRETURN;
}
void setup_sigtramp(abi_ulong sigtramp_page)
{
uint32_t *tramp = lock_user(VERIFY_WRITE, sigtramp_page, 2 * 8, 0);
assert(tramp != NULL);
#ifdef TARGET_ARCH_HAS_SETUP_FRAME
default_sigreturn = sigtramp_page;
install_sigtramp(tramp, TARGET_NR_sigreturn);
#endif
default_rt_sigreturn = sigtramp_page + 8;
install_sigtramp(tramp + 2, TARGET_NR_rt_sigreturn);
unlock_user(tramp, sigtramp_page, 2 * 8);
}
+1
View File
@@ -73,6 +73,7 @@ typedef struct target_sigaltstack {
/* compare linux/arch/mips/kernel/signal.c:setup_frame() */
#define TARGET_ARCH_HAS_SETUP_FRAME
#endif
#define TARGET_ARCH_HAS_SIGTRAMP_PAGE 1
/* bit-flags */
#define TARGET_SS_AUTODISARM (1U << 31) /* disable sas during sighandling */

Some files were not shown because too many files have changed in this diff Show More