[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Qemu-devel] [PATCH 13/23] bsd-user: add shims for signal related system
From: |
Stacey Son |
Subject: |
[Qemu-devel] [PATCH 13/23] bsd-user: add shims for signal related system calls |
Date: |
Sun, 23 Jun 2013 21:03:45 -0500 |
This change adds support for signal related system calls including sigaction(2),
sigprocmask(2), sigpending(2), sigsuspend(2), and so on. The older, obsolete,
system calls such as sigvec(2), sigblock(2), sigsetmask(2), and sigstack(2) are
not supported.
Signed-off-by: Stacey Son <address@hidden>
---
bsd-user/bsd-signal.h | 232 ++++++++++++++++++++++++++++++++++++++++++
bsd-user/freebsd/os-signal.h | 43 ++++++++
bsd-user/netbsd/os-signal.h | 34 ++++++
bsd-user/openbsd/os-signal.h | 34 ++++++
bsd-user/syscall.c | 57 ++++++++++
5 files changed, 400 insertions(+), 0 deletions(-)
create mode 100644 bsd-user/bsd-signal.h
create mode 100644 bsd-user/freebsd/os-signal.h
create mode 100644 bsd-user/netbsd/os-signal.h
create mode 100644 bsd-user/openbsd/os-signal.h
diff --git a/bsd-user/bsd-signal.h b/bsd-user/bsd-signal.h
new file mode 100644
index 0000000..48a8b56
--- /dev/null
+++ b/bsd-user/bsd-signal.h
@@ -0,0 +1,232 @@
+/*
+ * signal related system call shims
+ *
+ * Copyright (c) 2013 Stacey D. Son
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef __BSD_SIGNAL_H_
+#define __BSD_SIGNAL_H_
+
+/* sigaction(2) */
+static inline abi_long do_bsd_sigaction(abi_long arg1, abi_long arg2,
+ abi_long arg3)
+{
+ abi_long ret;
+ struct target_sigaction *old_act, act, oact, *pact;
+
+ if (arg2) {
+ if (!lock_user_struct(VERIFY_READ, old_act, arg2, 1)) {
+ return -TARGET_EFAULT;
+ }
+ act._sa_handler = old_act->_sa_handler;
+ act.sa_flags = old_act->sa_flags;
+ memcpy(&act.sa_mask, &old_act->sa_mask, sizeof(target_sigset_t));
+ unlock_user_struct(old_act, arg2, 0);
+ pact = &act;
+ } else {
+ pact = NULL;
+ }
+ ret = get_errno(do_sigaction(arg1, pact, &oact));
+ if (!is_error(ret) && arg3) {
+ if (!lock_user_struct(VERIFY_WRITE, old_act, arg3, 0)) {
+ return -TARGET_EFAULT;
+ }
+ old_act->_sa_handler = oact._sa_handler;
+ old_act->sa_flags = oact.sa_flags;
+ memcpy(&old_act->sa_mask, &oact.sa_mask, sizeof(target_sigset_t));
+ unlock_user_struct(old_act, arg3, 1);
+ }
+ return ret;
+}
+
+
+/* sigprocmask(2) */
+static inline abi_long do_bsd_sigprocmask(abi_long arg1, abi_ulong arg2,
+ abi_ulong arg3)
+{
+ abi_long ret;
+ void *p;
+ sigset_t set, oldset, *set_ptr;
+ int how;
+
+ if (arg2) {
+ switch (arg1) {
+ case TARGET_SIG_BLOCK:
+ how = SIG_BLOCK;
+ break;
+
+ case TARGET_SIG_UNBLOCK:
+ how = SIG_UNBLOCK;
+ break;
+
+ case TARGET_SIG_SETMASK:
+ how = SIG_SETMASK;
+ break;
+
+ default:
+ return -TARGET_EFAULT;
+ }
+ p = lock_user(VERIFY_READ, arg2, sizeof(target_sigset_t), 1);
+ if (p == NULL) {
+ return -TARGET_EFAULT;
+ }
+ target_to_host_sigset(&set, p);
+ unlock_user(p, arg2, 0);
+ set_ptr = &set;
+ } else {
+ how = 0;
+ set_ptr = NULL;
+ }
+ ret = get_errno(sigprocmask(how, set_ptr, &oldset));
+ if (!is_error(ret) && arg3) {
+ p = lock_user(VERIFY_WRITE, arg3, sizeof(target_sigset_t), 0);
+ if (p == NULL) {
+ return -TARGET_EFAULT;
+ }
+ host_to_target_sigset(p, &oldset);
+ unlock_user(p, arg3, sizeof(target_sigset_t));
+ }
+ return ret;
+}
+
+/* sigpending(2) */
+static inline abi_long do_bsd_sigpending(abi_long arg1)
+{
+ abi_long ret;
+ void *p;
+ sigset_t set;
+
+ ret = get_errno(sigpending(&set));
+ if (!is_error(ret)) {
+ p = lock_user(VERIFY_WRITE, arg1, sizeof(target_sigset_t), 0);
+ if (p == NULL) {
+ return -TARGET_EFAULT;
+ }
+ host_to_target_sigset(p, &set);
+ unlock_user(p, arg1, sizeof(target_sigset_t));
+ }
+ return ret;
+}
+
+/* sigsuspend(2) */
+static inline abi_long do_bsd_sigsuspend(abi_long arg1, abi_long arg2)
+{
+ void *p;
+ sigset_t set;
+
+ p = lock_user(VERIFY_READ, arg1, sizeof(target_sigset_t), 1);
+ if (p == NULL) {
+ return -TARGET_EFAULT;
+ }
+ target_to_host_sigset(&set, p);
+ unlock_user(p, arg1, 0);
+
+ return get_errno(sigsuspend(&set));
+}
+
+/* sigreturn(2) */
+static inline abi_long do_bsd_sigreturn(void *cpu_env, abi_long arg1)
+{
+
+ return do_sigreturn(cpu_env, arg1);
+}
+
+/* sigvec(2) - not defined */
+/* sigblock(2) - not defined */
+/* sigsetmask(2) - not defined */
+/* sigstack(2) - not defined */
+
+/* sigwait(2) */
+static inline abi_long do_bsd_sigwait(abi_ulong arg1, abi_ulong arg2,
+ abi_long arg3)
+{
+ abi_long ret;
+ void *p;
+ sigset_t set;
+ int sig;
+
+ p = lock_user(VERIFY_READ, arg1, sizeof(target_sigset_t), 1);
+ if (p == NULL) {
+ return -TARGET_EFAULT;
+ }
+ target_to_host_sigset(&set, p);
+ unlock_user(p, arg1, 0);
+ ret = get_errno(sigwait(&set, &sig));
+ if (!is_error(ret) && arg2) {
+ ret = put_user_s32(sig, arg2);
+ }
+ return ret;
+}
+
+/* sigwaitinfo(2) */
+static inline abi_long do_bsd_sigwaitinfo(abi_ulong arg1, abi_ulong arg2)
+{
+ abi_long ret;
+ void *p;
+ sigset_t set;
+ siginfo_t uinfo;
+
+ p = lock_user(VERIFY_READ, arg1, sizeof(target_sigset_t), 1);
+ if (p == NULL) {
+ return -TARGET_EFAULT;
+ }
+ target_to_host_sigset(&set, p);
+ unlock_user(p, arg1, 0);
+ ret = get_errno(sigwaitinfo(&set, &uinfo));
+ if (!is_error(ret) && arg2) {
+ p = lock_user(VERIFY_WRITE, arg2, sizeof(target_siginfo_t), 0);
+ if (p == NULL) {
+ return -TARGET_EFAULT;
+ }
+ host_to_target_siginfo(p, &uinfo);
+ unlock_user(p, arg2, sizeof(target_siginfo_t));
+ }
+ return ret;
+}
+
+/* sigqueue(2) */
+static inline abi_long do_bsd_sigqueue(abi_long arg1, abi_long arg2,
+ abi_ulong arg3)
+{
+ union sigval value;
+
+ value.sival_ptr = (void *)(uintptr_t)arg3;
+ return get_errno(sigqueue(arg1, target_to_host_signal(arg2), value));
+}
+
+/* sigaltstck(2) */
+static inline abi_long do_bsd_sigaltstack(void *cpu_env, abi_ulong arg1,
+ abi_ulong arg2)
+{
+
+ return do_sigaltstack(arg1, arg2, get_sp_from_cpustate(cpu_env));
+}
+
+/* kill(2) */
+static inline abi_long do_bsd_kill(abi_long pid, abi_long sig)
+{
+
+ return get_errno(kill(pid, target_to_host_signal(sig)));
+}
+
+/* killpg(2) */
+static inline abi_long do_bsd_killpg(abi_long pg, abi_long sig)
+{
+
+ return get_errno(killpg(pg, target_to_host_signal(sig)));
+}
+
+#endif /* ! __BSD_SIGNAL_H_ */
diff --git a/bsd-user/freebsd/os-signal.h b/bsd-user/freebsd/os-signal.h
new file mode 100644
index 0000000..d4a26da
--- /dev/null
+++ b/bsd-user/freebsd/os-signal.h
@@ -0,0 +1,43 @@
+/*
+ * FreeBSD signal system call shims
+ *
+ * Copyright (c) 2013 Stacey D. Son
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef __FREEBSD_OS_SIGNAL_H_
+#define __FREEBSD_OS_SIGNAL_H_
+
+#include <sys/procdesc.h>
+
+#if defined(__FreeBSD_version) && __FreeBSD_version > 900000
+/* pdkill(2) */
+static inline abi_long do_freebsd_pdkill(abi_long arg1, abi_long arg2)
+{
+
+ return get_errno(pdkill(arg1, arg2));
+}
+
+#else
+
+static inline abi_long do_freebsd_pdkill(abi_long arg1, abi_long arg2)
+{
+
+ qemu_log("qemu: Unsupported syscall pdkill()\n");
+ return -TARGET_ENOSYS;
+}
+#endif /* ! __FreeBSD_version > 900000 */
+
+#endif /* ! __FREEBSD_OS_SIGNAL_H_ */
diff --git a/bsd-user/netbsd/os-signal.h b/bsd-user/netbsd/os-signal.h
new file mode 100644
index 0000000..3ec4dfe
--- /dev/null
+++ b/bsd-user/netbsd/os-signal.h
@@ -0,0 +1,34 @@
+/*
+ * NetBSD signal system call shims
+ *
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef __NETBSD_OS_SIGNAL_H_
+#define __NETBSD_OS_SIGNAL_H_
+
+/*
+ * XXX To support FreeBSD binaries on NetBSD these syscalls will need
+ * to be emulated.
+ */
+
+static inline abi_long do_freebsd_pdkill(abi_long arg1, abi_long arg2)
+{
+
+ qemu_log("qemu: Unsupported syscall pdkill()\n");
+ return -TARGET_ENOSYS;
+}
+
+#endif /* ! __NETBSD_OS_SIGNAL_H_ */
diff --git a/bsd-user/openbsd/os-signal.h b/bsd-user/openbsd/os-signal.h
new file mode 100644
index 0000000..5ca80b3
--- /dev/null
+++ b/bsd-user/openbsd/os-signal.h
@@ -0,0 +1,34 @@
+/*
+ * OpenBSD signal system call shims
+ *
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef __OPENBSD_OS_SIGNAL_H_
+#define __OPENBSD_OS_SIGNAL_H_
+
+/*
+ * XXX To support FreeBSD binaries on OpenBSD these syscalls will need
+ * to be emulated.
+ */
+
+static inline abi_long do_freebsd_pdkill(abi_long arg1, abi_long arg2)
+{
+
+ qemu_log("qemu: Unsupported syscall pdkill()\n");
+ return -TARGET_ENOSYS;
+}
+
+#endif /* ! __OPENBSD_OS_SIGNAL_H_ */
diff --git a/bsd-user/syscall.c b/bsd-user/syscall.c
index cbdd363..a04c1bf 100644
--- a/bsd-user/syscall.c
+++ b/bsd-user/syscall.c
@@ -36,8 +36,10 @@
#include "bsd-errno.h"
#include "bsd-file.h"
#include "bsd-mem.h"
+#include "bsd-signal.h"
#include "os-time.h"
+#include "os-signal.h"
/* #define DEBUG */
@@ -777,6 +779,61 @@ abi_long do_freebsd_syscall(void *cpu_env, int num,
abi_long arg1,
ret = do_freebsd_kevent(arg1, arg2, arg3, arg4, arg5, arg6);
break;
+ /*
+ * signal system calls
+ */
+ case TARGET_FREEBSD_NR_sigtimedwait: /* sigtimedwait(2) */
+ ret = do_freebsd_sigtimedwait(arg1, arg2, arg3);
+ break;
+
+ case TARGET_FREEBSD_NR_sigaction: /* sigaction(2) */
+ ret = do_bsd_sigaction(arg1, arg2, arg3);
+ break;
+
+ case TARGET_FREEBSD_NR_sigprocmask: /* sigprocmask(2) */
+ ret = do_bsd_sigprocmask(arg1, arg2, arg3);
+ break;
+
+ case TARGET_FREEBSD_NR_sigpending: /* sigpending(2) */
+ ret = do_bsd_sigpending(arg1);
+ break;
+
+ case TARGET_FREEBSD_NR_sigsuspend: /* sigsuspend(2) */
+ ret = do_bsd_sigsuspend(arg1, arg2);
+ break;
+
+ case TARGET_FREEBSD_NR_sigreturn: /* sigreturn(2) */
+ ret = do_bsd_sigreturn(cpu_env, arg1);
+ break;
+
+ case TARGET_FREEBSD_NR_sigwait: /* sigwait(2) */
+ ret = do_bsd_sigwait(arg1, arg2, arg3);
+ break;
+
+ case TARGET_FREEBSD_NR_sigwaitinfo: /* sigwaitinfo(2) */
+ ret = do_bsd_sigwaitinfo(arg1, arg2);
+ break;
+
+ case TARGET_FREEBSD_NR_sigqueue: /* sigqueue(2) */
+ ret = do_bsd_sigqueue(arg1, arg2, arg3);
+ break;
+
+ case TARGET_FREEBSD_NR_sigaltstack: /* sigaltstack(2) */
+ ret = do_bsd_sigaltstack(cpu_env, arg1, arg2);
+ break;
+
+ case TARGET_FREEBSD_NR_kill: /* kill(2) */
+ ret = do_bsd_kill(arg1, arg2);
+ break;
+
+ case TARGET_FREEBSD_NR_killpg: /* killpg(2) */
+ ret = do_bsd_killpg(arg1, arg2);
+ break;
+
+ case TARGET_FREEBSD_NR_pdkill: /* pdkill(2) */
+ ret = do_freebsd_pdkill(arg1, arg2);
+ break;
+
case TARGET_FREEBSD_NR_break:
ret = do_obreak(arg1);
--
1.7.8
- [Qemu-devel] [PATCH 00/23] bsd-user: FreeBSD support for mips/mips64 and arm, Stacey Son, 2013/06/24
- [Qemu-devel] [PATCH 07/23] bsd-user: find target executable in path when absolute path not given, Stacey Son, 2013/06/24
- [Qemu-devel] [PATCH 05/23] bsd-user: add bsd_binprm to TaskState for core dumping emulation, Stacey Son, 2013/06/24
- [Qemu-devel] [PATCH 06/23] bsd-user: fix thread initialization and ELF addresses for mips/mips64, Stacey Son, 2013/06/24
- [Qemu-devel] [PATCH 13/23] bsd-user: add shims for signal related system calls,
Stacey Son <=
- [Qemu-devel] [PATCH 08/23] bsd-user: initialize stack with signal trampolin code and canary, Stacey Son, 2013/06/24
- [Qemu-devel] [PATCH 02/23] bsd-user: add initial support for mips/mips64, Stacey Son, 2013/06/24
- [Qemu-devel] [PATCH 01/23] bsd-user: initial code clean up, Stacey Son, 2013/06/24
- [Qemu-devel] [PATCH 11/23] bsd-user: add shims for file related system calls, Stacey Son, 2013/06/24
- [Qemu-devel] [PATCH 10/23] bsd-user: add shims for memory management related syscalls, Stacey Son, 2013/06/24
- [Qemu-devel] [PATCH 09/23] bsd-user: refresh FreeBSD's system call numbers, Stacey Son, 2013/06/24
- [Qemu-devel] [PATCH 12/23] bsd-user: add shims for time related system calls., Stacey Son, 2013/06/24