[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[PATCH v2 31/40] bsd-user/signal.c: setup_frame
From: |
Warner Losh |
Subject: |
[PATCH v2 31/40] bsd-user/signal.c: setup_frame |
Date: |
Mon, 24 Jan 2022 18:29:38 -0700 |
setup_frame sets up a signalled stack frame. Associated routines to
extract the pointer to the stack frame and to support alternate stacks.
Signed-off-by: Stacey Son <sson@FreeBSD.org>
Signed-off-by: Kyle Evans <kevans@freebsd.org>
Signed-off-by: Warner Losh <imp@bsdimp.com>
---
bsd-user/main.c | 5 +++
bsd-user/qemu.h | 3 +-
bsd-user/signal.c | 82 +++++++++++++++++++++++++++++++++++++++++++++++
3 files changed, 89 insertions(+), 1 deletion(-)
diff --git a/bsd-user/main.c b/bsd-user/main.c
index 29cf4e15693..f1d58e905e7 100644
--- a/bsd-user/main.c
+++ b/bsd-user/main.c
@@ -217,6 +217,11 @@ void qemu_cpu_kick(CPUState *cpu)
/* Assumes contents are already zeroed. */
static void init_task_state(TaskState *ts)
{
+ ts->sigaltstack_used = (struct target_sigaltstack) {
+ .ss_sp = 0,
+ .ss_size = 0,
+ .ss_flags = TARGET_SS_DISABLE,
+ };
}
void gemu_log(const char *fmt, ...)
diff --git a/bsd-user/qemu.h b/bsd-user/qemu.h
index fe0aedcdf3f..05be5de3f03 100644
--- a/bsd-user/qemu.h
+++ b/bsd-user/qemu.h
@@ -103,7 +103,8 @@ typedef struct TaskState {
*/
sigset_t signal_mask;
- uint8_t stack[];
+ /* This thread's sigaltstack, if it has one */
+ struct target_sigaltstack sigaltstack_used;
} __attribute__((aligned(16))) TaskState;
void stop_all_tasks(void);
diff --git a/bsd-user/signal.c b/bsd-user/signal.c
index 84dafa4e9fe..79a7083ddb3 100644
--- a/bsd-user/signal.c
+++ b/bsd-user/signal.c
@@ -35,6 +35,16 @@ static void host_signal_handler(int host_sig, siginfo_t
*info, void *puc);
static void target_to_host_sigset_internal(sigset_t *d,
const target_sigset_t *s);
+static inline int on_sig_stack(TaskState *ts, unsigned long sp)
+{
+ return sp - ts->sigaltstack_used.ss_sp < ts->sigaltstack_used.ss_size;
+}
+
+static inline int sas_ss_flags(TaskState *ts, unsigned long sp)
+{
+ return ts->sigaltstack_used.ss_size == 0 ? SS_DISABLE :
+ on_sig_stack(ts, sp) ? SS_ONSTACK : 0;
+}
/*
* The BSD ABIs use the same singal numbers across all the CPU architectures,
so
@@ -491,6 +501,78 @@ static void host_signal_handler(int host_sig, siginfo_t
*info, void *puc)
cpu_exit(thread_cpu);
}
+static inline abi_ulong get_sigframe(struct target_sigaction *ka,
+ CPUArchState *env, size_t frame_size)
+{
+ TaskState *ts = (TaskState *)thread_cpu->opaque;
+ abi_ulong sp;
+
+ /* Use default user stack */
+ sp = get_sp_from_cpustate(env);
+
+ if ((ka->sa_flags & TARGET_SA_ONSTACK) && sas_ss_flags(ts, sp) == 0) {
+ sp = ts->sigaltstack_used.ss_sp + ts->sigaltstack_used.ss_size;
+ }
+
+#if defined(TARGET_ARM)
+ return (sp - frame_size) & ~7;
+#elif defined(TARGET_AARCH64)
+ return (sp - frame_size) & ~15;
+#else
+ return sp - frame_size;
+#endif
+}
+
+/* compare to $M/$M/exec_machdep.c sendsig and sys/kern/kern_sig.c sigexit */
+
+static void setup_frame(int sig, int code, struct target_sigaction *ka,
+ target_sigset_t *set, target_siginfo_t *tinfo, CPUArchState *env)
+{
+ struct target_sigframe *frame;
+ abi_ulong frame_addr;
+ int i;
+
+ frame_addr = get_sigframe(ka, env, sizeof(*frame));
+ trace_user_setup_frame(env, frame_addr);
+ if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0)) {
+ unlock_user_struct(frame, frame_addr, 1);
+ dump_core_and_abort(TARGET_SIGILL);
+ return;
+ }
+
+ memset(frame, 0, sizeof(*frame));
+ setup_sigframe_arch(env, frame_addr, frame, 0);
+
+ for (i = 0; i < TARGET_NSIG_WORDS; i++) {
+ __put_user(set->__bits[i], &frame->sf_uc.uc_sigmask.__bits[i]);
+ }
+
+ if (tinfo) {
+ frame->sf_si.si_signo = tinfo->si_signo;
+ frame->sf_si.si_errno = tinfo->si_errno;
+ frame->sf_si.si_code = tinfo->si_code;
+ frame->sf_si.si_pid = tinfo->si_pid;
+ frame->sf_si.si_uid = tinfo->si_uid;
+ frame->sf_si.si_status = tinfo->si_status;
+ frame->sf_si.si_addr = tinfo->si_addr;
+ /* see host_to_target_siginfo_noswap() for more details */
+ frame->sf_si.si_value.sival_ptr = tinfo->si_value.sival_ptr;
+ /*
+ * At this point, whatever is in the _reason union is complete
+ * and in target order, so just copy the whole thing over, even
+ * if it's too large for this specific signal.
+ * host_to_target_siginfo_noswap() and tswap_siginfo() have ensured
+ * that's so.
+ */
+ memcpy(&frame->sf_si._reason, &tinfo->_reason,
+ sizeof(tinfo->_reason));
+ }
+
+ set_sigtramp_args(env, sig, frame, frame_addr, ka);
+
+ unlock_user_struct(frame, frame_addr, 1);
+}
+
void signal_init(void)
{
TaskState *ts = (TaskState *)thread_cpu->opaque;
--
2.33.1
- Re: [PATCH v2 30/40] bsd-user/signal.c: sigset manipulation routines., (continued)
- [PATCH v2 35/40] bsd-user/signal.c: implement do_sigreturn, Warner Losh, 2022/01/24
- [PATCH v2 33/40] bsd-user/signal.c: tswap_siginfo, Warner Losh, 2022/01/24
- [PATCH v2 40/40] bsd-user/freebsd/target_os_ucontext.h: Prefer env as arg name for CPUArchState args, Warner Losh, 2022/01/24
- [PATCH v2 24/40] bsd-user/signal.c: host_to_target_siginfo_noswap, Warner Losh, 2022/01/24
- [PATCH v2 20/40] bsd-user/host/i386/host-signal.h: Implement host_signal_*, Warner Losh, 2022/01/24
- [PATCH v2 25/40] bsd-user/signal.c: Implement rewind_if_in_safe_syscall, Warner Losh, 2022/01/24
- [PATCH v2 31/40] bsd-user/signal.c: setup_frame,
Warner Losh <=
- [PATCH v2 32/40] bsd-user/signal.c: handle_pending_signal, Warner Losh, 2022/01/24
- [PATCH v2 34/40] bsd-user/signal.c: process_pending_signals, Warner Losh, 2022/01/24
- [PATCH v2 37/40] bsd-user/signal.c: do_sigaltstack, Warner Losh, 2022/01/24
- [PATCH v2 36/40] bsd-user/signal.c: implement do_sigaction, Warner Losh, 2022/01/24