Page MenuHomeFreeBSD

D7974.diff
No OneTemporary

D7974.diff

Index: sys/arm/linux/linux.h
===================================================================
--- /dev/null
+++ sys/arm/linux/linux.h
@@ -0,0 +1,595 @@
+/*-
+ * Copyright (c) 1994-1996 Søren Schmidt
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer
+ * in this position and unchanged.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+#ifndef _ARM_LINUX_H_
+#define _ARM_LINUX_H_
+
+#include <sys/signal.h> /* for sigval union */
+
+#include <compat/linux/linux.h>
+#include <arm/linux/linux_syscall.h>
+
+/*
+ * debugging support
+ */
+extern u_char linux_debug_map[];
+#define ldebug(name) isclr(linux_debug_map, LINUX_SYS_linux_ ## name)
+#define ARGS(nm, fmt) "linux(%ld/%ld): "#nm"("fmt")\n", \
+ (long)td->td_proc->p_pid, (long)td->td_tid
+#define LMSG(fmt) "linux(%ld/%ld): "fmt"\n", \
+ (long)td->td_proc->p_pid, (long)td->td_tid
+#define LINUX_DTRACE linuxulator
+
+#define LINUX_SHAREDPAGE (VM_MAXUSER_ADDRESS - PAGE_SIZE)
+#define LINUX_USRSTACK LINUX_SHAREDPAGE
+
+#define PTRIN(v) (void *)(v)
+#define PTROUT(v) (l_uintptr_t)(v)
+
+#define CP(src,dst,fld) do { (dst).fld = (src).fld; } while (0)
+#define CP2(src,dst,sfld,dfld) do { (dst).dfld = (src).sfld; } while (0)
+#define PTRIN_CP(src,dst,fld) \
+ do { (dst).fld = PTRIN((src).fld); } while (0)
+
+/*
+ * Provide a separate set of types for the Linux types.
+ */
+typedef int l_int;
+typedef int32_t l_long;
+typedef int64_t l_longlong;
+typedef short l_short;
+typedef unsigned int l_uint;
+typedef uint32_t l_ulong;
+typedef uint64_t l_ulonglong;
+typedef unsigned short l_ushort;
+
+typedef char *l_caddr_t;
+typedef l_ulong l_uintptr_t;
+typedef l_long l_clock_t;
+typedef l_int l_daddr_t;
+typedef l_ushort l_dev_t;
+typedef l_uint l_gid_t;
+typedef l_ushort l_gid16_t;
+typedef l_ulong l_ino_t;
+typedef l_int l_key_t;
+typedef l_longlong l_loff_t;
+typedef l_ushort l_mode_t;
+typedef l_long l_off_t;
+typedef l_int l_pid_t;
+typedef l_uint l_size_t;
+typedef l_long l_suseconds_t;
+typedef l_long l_time_t;
+typedef l_uint l_uid_t;
+typedef l_ushort l_uid16_t;
+typedef l_int l_timer_t;
+typedef l_int l_mqd_t;
+typedef l_ulong l_fd_mask;
+
+typedef struct {
+ l_int val[2];
+} __packed l_fsid_t;
+
+typedef struct {
+ l_time_t tv_sec;
+ l_suseconds_t tv_usec;
+} l_timeval;
+
+#define l_fd_set fd_set
+
+/*
+ * Miscellaneous
+ */
+#define LINUX_AT_COUNT 20 /* Count of used aux entry types.
+ * Keep this synchronized with
+ * elf_linux_fixup() code.
+ */
+struct l___sysctl_args
+{
+ l_int *name;
+ l_int nlen;
+ void *oldval;
+ l_size_t *oldlenp;
+ void *newval;
+ l_size_t newlen;
+ l_ulong __spare[4];
+};
+
+/* Resource limits */
+#define LINUX_RLIMIT_CPU 0
+#define LINUX_RLIMIT_FSIZE 1
+#define LINUX_RLIMIT_DATA 2
+#define LINUX_RLIMIT_STACK 3
+#define LINUX_RLIMIT_CORE 4
+#define LINUX_RLIMIT_RSS 5
+#define LINUX_RLIMIT_NPROC 6
+#define LINUX_RLIMIT_NOFILE 7
+#define LINUX_RLIMIT_MEMLOCK 8
+#define LINUX_RLIMIT_AS 9 /* Address space limit */
+
+#define LINUX_RLIM_NLIMITS 10
+
+struct l_rlimit {
+ l_ulong rlim_cur;
+ l_ulong rlim_max;
+} __packed;
+
+/* mmap options */
+#define LINUX_MAP_SHARED 0x0001
+#define LINUX_MAP_PRIVATE 0x0002
+#define LINUX_MAP_FIXED 0x0010
+#define LINUX_MAP_ANON 0x0020
+#define LINUX_MAP_GROWSDOWN 0x0100
+
+struct l_mmap_argv {
+ l_uintptr_t addr;
+ l_size_t len;
+ l_int prot;
+ l_int flags;
+ l_int fd;
+ l_off_t pgoff;
+} __packed;
+
+/*
+ * stat family of syscalls
+ */
+struct l_timespec {
+ l_time_t tv_sec;
+ l_long tv_nsec;
+} __packed;
+
+struct l_newstat {
+ l_ushort st_dev;
+ l_ushort __pad1;
+ l_ulong st_ino;
+ l_ushort st_mode;
+ l_ushort st_nlink;
+ l_ushort st_uid;
+ l_ushort st_gid;
+ l_ushort st_rdev;
+ l_ushort __pad2;
+ l_ulong st_size;
+ l_ulong st_blksize;
+ l_ulong st_blocks;
+ struct l_timespec st_atim;
+ struct l_timespec st_mtim;
+ struct l_timespec st_ctim;
+ l_ulong __unused4;
+ l_ulong __unused5;
+} __packed;
+
+struct l_stat {
+ l_ushort st_dev;
+ l_ulong st_ino;
+ l_ushort st_mode;
+ l_ushort st_nlink;
+ l_ushort st_uid;
+ l_ushort st_gid;
+ l_ushort st_rdev;
+ l_long st_size;
+ struct l_timespec st_atim;
+ struct l_timespec st_mtim;
+ struct l_timespec st_ctim;
+ l_long st_blksize;
+ l_long st_blocks;
+ l_ulong st_flags;
+ l_ulong st_gen;
+};
+
+struct l_stat64 {
+ l_ushort st_dev;
+ u_char __pad0[10];
+ l_ulong __st_ino;
+ l_uint st_mode;
+ l_uint st_nlink;
+ l_ulong st_uid;
+ l_ulong st_gid;
+ l_ushort st_rdev;
+ u_char __pad3[10];
+ l_longlong st_size;
+ l_ulong st_blksize;
+ l_ulong st_blocks;
+ l_ulong __pad4;
+ struct l_timespec st_atim;
+ struct l_timespec st_mtim;
+ struct l_timespec st_ctim;
+ l_ulonglong st_ino;
+} __packed;
+
+struct l_statfs64 {
+ l_int f_type;
+ l_int f_bsize;
+ uint64_t f_blocks;
+ uint64_t f_bfree;
+ uint64_t f_bavail;
+ uint64_t f_files;
+ uint64_t f_ffree;
+ l_fsid_t f_fsid;
+ l_int f_namelen;
+ l_int f_spare[6];
+} __packed;
+
+#define LINUX_NSIG_WORDS 2
+
+/* sigaction flags */
+#define LINUX_SA_NOCLDSTOP 0x00000001
+#define LINUX_SA_NOCLDWAIT 0x00000002
+#define LINUX_SA_SIGINFO 0x00000004
+#define LINUX_SA_RESTORER 0x04000000
+#define LINUX_SA_ONSTACK 0x08000000
+#define LINUX_SA_RESTART 0x10000000
+#define LINUX_SA_INTERRUPT 0x20000000
+#define LINUX_SA_NOMASK 0x40000000
+#define LINUX_SA_ONESHOT 0x80000000
+
+/* sigprocmask actions */
+#define LINUX_SIG_BLOCK 0
+#define LINUX_SIG_UNBLOCK 1
+#define LINUX_SIG_SETMASK 2
+
+/* sigaltstack */
+#define LINUX_MINSIGSTKSZ 2048
+
+typedef void (*l_handler_t)(l_int);
+typedef l_ulong l_osigset_t;
+
+typedef struct {
+ l_handler_t lsa_handler;
+ l_osigset_t lsa_mask;
+ l_ulong lsa_flags;
+ void (*lsa_restorer)(void);
+} __packed l_osigaction_t;
+
+typedef struct {
+ l_handler_t lsa_handler;
+ l_ulong lsa_flags;
+ void (*lsa_restorer)(void);
+ l_sigset_t lsa_mask;
+} __packed l_sigaction_t;
+
+typedef struct {
+ void *ss_sp;
+ l_int ss_flags;
+ l_size_t ss_size;
+} __packed l_stack_t;
+
+/* The Linux sigcontext, pretty much a standard 386 trapframe. */
+struct l_sigcontext {
+ unsigned long trap_no;
+ unsigned long error_code;
+ unsigned long oldmask;
+ unsigned long arm_r0;
+ unsigned long arm_r1;
+ unsigned long arm_r2;
+ unsigned long arm_r3;
+ unsigned long arm_r4;
+ unsigned long arm_r5;
+ unsigned long arm_r6;
+ unsigned long arm_r7;
+ unsigned long arm_r8;
+ unsigned long arm_r9;
+ unsigned long arm_r10;
+ unsigned long arm_fp;
+ unsigned long arm_ip;
+ unsigned long arm_sp;
+ unsigned long arm_lr;
+ unsigned long arm_pc;
+ unsigned long arm_cpsr;
+ unsigned long fault_address;
+} __packed;
+
+struct l_ucontext {
+ l_ulong uc_flags;
+ void *uc_link;
+ l_stack_t uc_stack;
+ struct l_sigcontext uc_mcontext;
+ l_sigset_t uc_sigmask;
+} __packed;
+
+#define LINUX_SI_MAX_SIZE 128
+#define LINUX_SI_PAD_SIZE ((LINUX_SI_MAX_SIZE/sizeof(l_int)) - 3)
+
+typedef union l_sigval {
+ l_int sival_int;
+ l_uintptr_t sival_ptr;
+} l_sigval_t;
+
+typedef struct l_siginfo {
+ l_int lsi_signo;
+ l_int lsi_errno;
+ l_int lsi_code;
+ union {
+ l_int _pad[LINUX_SI_PAD_SIZE];
+
+ struct {
+ l_pid_t _pid;
+ l_uid_t _uid;
+ } __packed _kill;
+
+ struct {
+ l_timer_t _tid;
+ l_int _overrun;
+ char _pad[sizeof(l_uid_t) - sizeof(l_int)];
+ l_sigval_t _sigval;
+ l_int _sys_private;
+ } __packed _timer;
+
+ struct {
+ l_pid_t _pid; /* sender's pid */
+ l_uid_t _uid; /* sender's uid */
+ l_sigval_t _sigval;
+ } __packed _rt;
+
+ struct {
+ l_pid_t _pid; /* which child */
+ l_uid_t _uid; /* sender's uid */
+ l_int _status; /* exit code */
+ l_clock_t _utime;
+ l_clock_t _stime;
+ } __packed _sigchld;
+
+ struct {
+ l_uintptr_t _addr; /* Faulting insn/memory ref. */
+ } __packed _sigfault;
+
+ struct {
+ l_long _band; /* POLL_IN,POLL_OUT,POLL_MSG */
+ l_int _fd;
+ } __packed _sigpoll;
+ } _sifields;
+} __packed l_siginfo_t;
+
+#define lsi_pid _sifields._kill._pid
+#define lsi_uid _sifields._kill._uid
+#define lsi_tid _sifields._timer._tid
+#define lsi_overrun _sifields._timer._overrun
+#define lsi_sys_private _sifields._timer._sys_private
+#define lsi_status _sifields._sigchld._status
+#define lsi_utime _sifields._sigchld._utime
+#define lsi_stime _sifields._sigchld._stime
+#define lsi_value _sifields._rt._sigval
+#define lsi_int _sifields._rt._sigval.sival_int
+#define lsi_ptr _sifields._rt._sigval.sival_ptr
+#define lsi_addr _sifields._sigfault._addr
+#define lsi_band _sifields._sigpoll._band
+#define lsi_fd _sifields._sigpoll._fd
+
+struct l_fpreg {
+ u_int16_t significand[4];
+ u_int16_t exponent;
+} __packed;
+
+struct l_fpxreg {
+ u_int16_t significand[4];
+ u_int16_t exponent;
+ u_int16_t padding[3];
+} __packed;
+
+struct l_xmmreg {
+ u_int32_t element[4];
+} __packed;
+
+struct l_fpstate {
+ /* Regular FPU environment */
+ u_int32_t cw;
+ u_int32_t sw;
+ u_int32_t tag;
+ u_int32_t ipoff;
+ u_int32_t cssel;
+ u_int32_t dataoff;
+ u_int32_t datasel;
+ struct l_fpreg _st[8];
+ u_int16_t status;
+ u_int16_t magic; /* 0xffff = regular FPU data */
+
+ /* FXSR FPU environment */
+ u_int32_t _fxsr_env[6]; /* env is ignored. */
+ u_int32_t mxcsr;
+ u_int32_t reserved;
+ struct l_fpxreg _fxsr_st[8]; /* reg data is ignored. */
+ struct l_xmmreg _xmm[8];
+ u_int32_t padding[56];
+} __packed;
+
+/*
+ * We make the stack look like Linux expects it when calling a signal
+ * handler, but use the BSD way of calling the handler and sigreturn().
+ * This means that we need to pass the pointer to the handler too.
+ * It is appended to the frame to not interfere with the rest of it.
+ */
+struct l_sigframe {
+ l_int sf_sig;
+ struct l_sigcontext sf_sc;
+ struct l_fpstate sf_fpstate;
+ l_uint sf_extramask[LINUX_NSIG_WORDS-1];
+ l_handler_t sf_handler;
+} __packed;
+
+struct l_rt_sigframe {
+ l_int sf_sig;
+ l_siginfo_t *sf_siginfo;
+ struct l_ucontext *sf_ucontext;
+ l_siginfo_t sf_si;
+ struct l_ucontext sf_sc;
+ l_handler_t sf_handler;
+} __packed;
+
+extern struct sysentvec linux_sysvec;
+
+/*
+ * arch specific open/fcntl flags
+ */
+#define LINUX_F_GETLK64 12
+#define LINUX_F_SETLK64 13
+#define LINUX_F_SETLKW64 14
+
+union l_semun {
+ l_int val;
+ struct l_semid_ds *buf;
+ l_ushort *array;
+ struct l_seminfo *__buf;
+ void *__pad;
+} __packed;
+
+struct l_ipc_perm {
+ l_key_t key;
+ l_uid16_t uid;
+ l_gid16_t gid;
+ l_uid16_t cuid;
+ l_gid16_t cgid;
+ l_ushort mode;
+ l_ushort seq;
+};
+
+/*
+ * Socket defines
+ */
+#define LINUX_SOL_SOCKET 1
+#define LINUX_SOL_IP 0
+#define LINUX_SOL_IPX 256
+#define LINUX_SOL_AX25 257
+#define LINUX_SOL_TCP 6
+#define LINUX_SOL_UDP 17
+
+#define LINUX_SO_DEBUG 1
+#define LINUX_SO_REUSEADDR 2
+#define LINUX_SO_TYPE 3
+#define LINUX_SO_ERROR 4
+#define LINUX_SO_DONTROUTE 5
+#define LINUX_SO_BROADCAST 6
+#define LINUX_SO_SNDBUF 7
+#define LINUX_SO_RCVBUF 8
+#define LINUX_SO_KEEPALIVE 9
+#define LINUX_SO_OOBINLINE 10
+#define LINUX_SO_NO_CHECK 11
+#define LINUX_SO_PRIORITY 12
+#define LINUX_SO_LINGER 13
+#define LINUX_SO_PEERCRED 17
+#define LINUX_SO_RCVLOWAT 18
+#define LINUX_SO_SNDLOWAT 19
+#define LINUX_SO_RCVTIMEO 20
+#define LINUX_SO_SNDTIMEO 21
+#define LINUX_SO_TIMESTAMP 29
+#define LINUX_SO_ACCEPTCONN 30
+
+struct l_sockaddr {
+ l_ushort sa_family;
+ char sa_data[14];
+};
+
+struct l_ifmap {
+ l_ulong mem_start;
+ l_ulong mem_end;
+ l_ushort base_addr;
+ u_char irq;
+ u_char dma;
+ u_char port;
+} __packed;
+
+#define LINUX_IFHWADDRLEN 6
+#define LINUX_IFNAMSIZ 16
+
+struct l_ifreq {
+ union {
+ char ifrn_name[LINUX_IFNAMSIZ];
+ } ifr_ifrn;
+
+ union {
+ struct l_sockaddr ifru_addr;
+ struct l_sockaddr ifru_dstaddr;
+ struct l_sockaddr ifru_broadaddr;
+ struct l_sockaddr ifru_netmask;
+ struct l_sockaddr ifru_hwaddr;
+ l_short ifru_flags[1];
+ l_int ifru_metric;
+ l_int ifru_mtu;
+ struct l_ifmap ifru_map;
+ char ifru_slave[LINUX_IFNAMSIZ];
+ l_caddr_t ifru_data;
+ } ifr_ifru;
+} __packed;
+
+#define ifr_name ifr_ifrn.ifrn_name /* Interface name */
+#define ifr_hwaddr ifr_ifru.ifru_hwaddr /* MAC address */
+
+/*
+ * poll()
+ */
+#define LINUX_POLLIN 0x0001
+#define LINUX_POLLPRI 0x0002
+#define LINUX_POLLOUT 0x0004
+#define LINUX_POLLERR 0x0008
+#define LINUX_POLLHUP 0x0010
+#define LINUX_POLLNVAL 0x0020
+#define LINUX_POLLRDNORM 0x0040
+#define LINUX_POLLRDBAND 0x0080
+#define LINUX_POLLWRNORM 0x0100
+#define LINUX_POLLWRBAND 0x0200
+#define LINUX_POLLMSG 0x0400
+
+struct l_pollfd {
+ l_int fd;
+ l_short events;
+ l_short revents;
+} __packed;
+
+struct l_user_desc {
+ l_uint entry_number;
+ l_uint base_addr;
+ l_uint limit;
+ l_uint seg_32bit:1;
+ l_uint contents:2;
+ l_uint read_exec_only:1;
+ l_uint limit_in_pages:1;
+ l_uint seg_not_present:1;
+ l_uint useable:1;
+};
+
+struct l_desc_struct {
+ unsigned long a, b;
+};
+
+#define linux_copyout_rusage(r, u) copyout(r, u, sizeof(*r))
+
+/* robust futexes */
+struct linux_robust_list {
+ struct linux_robust_list *next;
+};
+
+struct linux_robust_list_head {
+ struct linux_robust_list list;
+ l_long futex_offset;
+ struct linux_robust_list *pending_list;
+};
+
+#define LINUX_GETTLS_HELPER 0xffff0fe0
+
+uint32_t linux_get_tls(struct thread *td);
+
+#endif /* !_ARM_LINUX_H_ */
Index: sys/arm/linux/linux_dummy.c
===================================================================
--- /dev/null
+++ sys/arm/linux/linux_dummy.c
@@ -0,0 +1,134 @@
+/*-
+ * Copyright (c) 1994-1995 Søren Schmidt
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer
+ * in this position and unchanged.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include "opt_compat.h"
+
+#include <sys/param.h>
+#include <sys/kernel.h>
+#include <sys/sdt.h>
+#include <sys/systm.h>
+#include <sys/proc.h>
+
+#include <arm/linux/linux.h>
+#include <arm/linux/linux_proto.h>
+#include <compat/linux/linux_dtrace.h>
+#include <compat/linux/linux_util.h>
+
+/* DTrace init */
+LIN_SDT_PROVIDER_DECLARE(LINUX_DTRACE);
+
+DUMMY(syslog);
+DUMMY(vhangup);
+DUMMY(swapoff);
+DUMMY(adjtimex);
+DUMMY(init_module);
+DUMMY(delete_module);
+DUMMY(quotactl);
+DUMMY(bdflush);
+DUMMY(sysfs);
+DUMMY(sendfile); /* different semantics */
+DUMMY(setfsuid);
+DUMMY(setfsgid);
+DUMMY(pivot_root);
+DUMMY(mincore);
+DUMMY(lookup_dcookie);
+DUMMY(remap_file_pages);
+DUMMY(mbind);
+DUMMY(get_mempolicy);
+DUMMY(set_mempolicy);
+DUMMY(kexec_load);
+/* linux 2.6.11: */
+DUMMY(add_key);
+DUMMY(request_key);
+DUMMY(keyctl);
+/* linux 2.6.13: */
+DUMMY(ioprio_set);
+DUMMY(ioprio_get);
+DUMMY(inotify_init);
+DUMMY(inotify_add_watch);
+DUMMY(inotify_rm_watch);
+/* linux 2.6.16: */
+DUMMY(unshare);
+/* linux 2.6.17: */
+DUMMY(splice);
+DUMMY(sync_file_range);
+DUMMY(tee);
+DUMMY(vmsplice);
+/* linux 2.6.18: */
+DUMMY(move_pages);
+/* linux 2.6.19: */
+DUMMY(getcpu);
+/* linux 2.6.22: */
+DUMMY(signalfd);
+DUMMY(timerfd_create);
+/* linux 2.6.25: */
+DUMMY(timerfd_settime);
+DUMMY(timerfd_gettime);
+/* linux 2.6.27: */
+DUMMY(signalfd4);
+DUMMY(inotify_init1);
+/* linux 2.6.30: */
+DUMMY(preadv);
+DUMMY(pwritev);
+/* linux 2.6.31 */
+DUMMY(rt_tsigqueueinfo);
+DUMMY(perf_event_open);
+/* linux 2.6.33: */
+DUMMY(fanotify_init);
+DUMMY(fanotify_mark);
+/* later: */
+DUMMY(name_to_handle_at);
+DUMMY(open_by_handle_at);
+DUMMY(clock_adjtime);
+DUMMY(setns);
+DUMMY(process_vm_readv);
+DUMMY(process_vm_writev);
+
+#define DUMMY_XATTR(s) \
+int \
+linux_ ## s ## xattr( \
+ struct thread *td, struct linux_ ## s ## xattr_args *arg) \
+{ \
+ \
+ return (ENOATTR); \
+}
+DUMMY_XATTR(set);
+DUMMY_XATTR(lset);
+DUMMY_XATTR(fset);
+DUMMY_XATTR(get);
+DUMMY_XATTR(lget);
+DUMMY_XATTR(fget);
+DUMMY_XATTR(list);
+DUMMY_XATTR(llist);
+DUMMY_XATTR(flist);
+DUMMY_XATTR(remove);
+DUMMY_XATTR(lremove);
+DUMMY_XATTR(fremove);
Index: sys/arm/linux/linux_genassym.c
===================================================================
--- /dev/null
+++ sys/arm/linux/linux_genassym.c
@@ -0,0 +1,18 @@
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/param.h>
+#include <sys/assym.h>
+#include <sys/systm.h>
+
+#include <arm/linux/linux.h>
+#include <compat/linux/linux_mib.h>
+
+ASSYM(LINUX_SIGF_HANDLER, offsetof(struct l_sigframe, sf_handler));
+ASSYM(LINUX_SIGF_SC, offsetof(struct l_sigframe, sf_sc));
+ASSYM(LINUX_SC_EFLAGS, offsetof(struct l_sigcontext, arm_cpsr));
+ASSYM(LINUX_RT_SIGF_HANDLER, offsetof(struct l_rt_sigframe, sf_handler));
+ASSYM(LINUX_RT_SIGF_UC, offsetof(struct l_rt_sigframe, sf_sc));
+ASSYM(LINUX_RT_SIGF_SC, offsetof(struct l_ucontext, uc_mcontext));
+ASSYM(LINUX_SC_ESP, offsetof(struct l_sigcontext, arm_sp));
+ASSYM(LINUX_VERSION_CODE, LINUX_VERSION_CODE);
Index: sys/arm/linux/linux_ipc64.h
===================================================================
--- /dev/null
+++ sys/arm/linux/linux_ipc64.h
@@ -0,0 +1,145 @@
+/*-
+ * Copyright (c) 2002 Maxim Sobolev <sobomax@FreeBSD.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer
+ * in this position and unchanged.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+#ifndef _ARM_LINUX_LINUX_IPC64_H_
+#define _ARM_LINUX_LINUX_IPC64_H_
+
+/*
+ * The ipc64_perm structure for i386 architecture.
+ * Note extra padding because this structure is passed back and forth
+ * between kernel and user space.
+ *
+ * Pad space is left for:
+ * - 32-bit mode_t and seq
+ * - 2 miscellaneous 32-bit values
+ */
+
+struct l_ipc64_perm
+{
+ l_key_t key;
+ l_uid_t uid;
+ l_gid_t gid;
+ l_uid_t cuid;
+ l_gid_t cgid;
+ l_mode_t mode;
+ l_ushort __pad1;
+ l_ushort seq;
+ l_ushort __pad2;
+ l_ulong __unused1;
+ l_ulong __unused2;
+} __packed;
+
+/*
+ * The msqid64_ds structure for i386 architecture.
+ * Note extra padding because this structure is passed back and forth
+ * between kernel and user space.
+ *
+ * Pad space is left for:
+ * - 64-bit time_t to solve y2038 problem
+ * - 2 miscellaneous 32-bit values
+ */
+
+struct l_msqid64_ds {
+ struct l_ipc64_perm msg_perm;
+ l_time_t msg_stime; /* last msgsnd time */
+ l_ulong __unused1;
+ l_time_t msg_rtime; /* last msgrcv time */
+ l_ulong __unused2;
+ l_time_t msg_ctime; /* last change time */
+ l_ulong __unused3;
+ l_ulong msg_cbytes; /* current number of bytes on queue */
+ l_ulong msg_qnum; /* number of messages in queue */
+ l_ulong msg_qbytes; /* max number of bytes on queue */
+ l_pid_t msg_lspid; /* pid of last msgsnd */
+ l_pid_t msg_lrpid; /* last receive pid */
+ l_ulong __unused4;
+ l_ulong __unused5;
+} __packed;
+
+/*
+ * The semid64_ds structure for i386 architecture.
+ * Note extra padding because this structure is passed back and forth
+ * between kernel and user space.
+ *
+ * Pad space is left for:
+ * - 64-bit time_t to solve y2038 problem
+ * - 2 miscellaneous 32-bit values
+ */
+
+struct l_semid64_ds {
+ struct l_ipc64_perm sem_perm; /* permissions */
+ l_time_t sem_otime; /* last semop time */
+ l_ulong __unused1;
+ l_time_t sem_ctime; /* last change time */
+ l_ulong __unused2;
+ l_ulong sem_nsems; /* no. of semaphores in array */
+ l_ulong __unused3;
+ l_ulong __unused4;
+} __packed;
+
+/*
+ * The shmid64_ds structure for i386 architecture.
+ * Note extra padding because this structure is passed back and forth
+ * between kernel and user space.
+ *
+ * Pad space is left for:
+ * - 64-bit time_t to solve y2038 problem
+ * - 2 miscellaneous 32-bit values
+ */
+
+struct l_shmid64_ds {
+ struct l_ipc64_perm shm_perm; /* operation perms */
+ l_size_t shm_segsz; /* size of segment (bytes) */
+ l_time_t shm_atime; /* last attach time */
+ l_ulong __unused1;
+ l_time_t shm_dtime; /* last detach time */
+ l_ulong __unused2;
+ l_time_t shm_ctime; /* last change time */
+ l_ulong __unused3;
+ l_pid_t shm_cpid; /* pid of creator */
+ l_pid_t shm_lpid; /* pid of last operator */
+ l_ulong shm_nattch; /* no. of current attaches */
+ l_ulong __unused4;
+ l_ulong __unused5;
+} __packed;
+
+struct l_shminfo64 {
+ l_ulong shmmax;
+ l_ulong shmmin;
+ l_ulong shmmni;
+ l_ulong shmseg;
+ l_ulong shmall;
+ l_ulong __unused1;
+ l_ulong __unused2;
+ l_ulong __unused3;
+ l_ulong __unused4;
+} __packed;
+
+#endif /* !_ARM_LINUX_LINUX_IPC64_H_ */
Index: sys/arm/linux/linux_machdep.c
===================================================================
--- /dev/null
+++ sys/arm/linux/linux_machdep.c
@@ -0,0 +1,656 @@
+/*-
+ * Copyright (c) 2000 Marcel Moolenaar
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer
+ * in this position and unchanged.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/capsicum.h>
+#include <sys/file.h>
+#include <sys/fcntl.h>
+#include <sys/imgact.h>
+#include <sys/lock.h>
+#include <sys/malloc.h>
+#include <sys/mman.h>
+#include <sys/mutex.h>
+#include <sys/sx.h>
+#include <sys/priv.h>
+#include <sys/proc.h>
+#include <sys/queue.h>
+#include <sys/resource.h>
+#include <sys/resourcevar.h>
+#include <sys/signalvar.h>
+#include <sys/syscallsubr.h>
+#include <sys/sysproto.h>
+#include <sys/unistd.h>
+#include <sys/wait.h>
+#include <sys/sched.h>
+#include <sys/clock.h>
+
+#include <machine/frame.h>
+#include <machine/psl.h>
+#include <machine/sysarch.h>
+
+#include <vm/vm.h>
+#include <vm/pmap.h>
+#include <vm/vm_map.h>
+
+#include <arm/linux/linux.h>
+#include <arm/linux/linux_proto.h>
+#include <compat/linux/linux_ipc.h>
+#include <compat/linux/linux_misc.h>
+#include <compat/linux/linux_signal.h>
+#include <compat/linux/linux_util.h>
+#include <compat/linux/linux_emul.h>
+
+#include <machine/pcb.h> /* needed for pcb definition in linux_set_thread_area */
+
+#include "opt_posix.h"
+
+extern struct sysentvec elf32_freebsd_sysvec; /* defined in i386/i386/elf_machdep.c */
+
+struct l_old_select_argv {
+ l_int nfds;
+ l_fd_set *readfds;
+ l_fd_set *writefds;
+ l_fd_set *exceptfds;
+ struct l_timeval *timeout;
+};
+
+static int linux_mmap_common(struct thread *td, l_uintptr_t addr,
+ l_size_t len, l_int prot, l_int flags, l_int fd,
+ l_loff_t pos);
+
+
+int
+linux_execve(struct thread *td, struct linux_execve_args *args)
+{
+ struct image_args eargs;
+ char *newpath;
+ int error;
+
+ LCONVPATHEXIST(td, args->path, &newpath);
+
+#ifdef DEBUG
+ if (ldebug(execve))
+ printf(ARGS(execve, "%s"), newpath);
+#endif
+
+ error = exec_copyin_args(&eargs, newpath, UIO_SYSSPACE,
+ args->argp, args->envp);
+ free(newpath, M_TEMP);
+ if (error == 0)
+ error = linux_common_execve(td, &eargs);
+ return (error);
+}
+
+struct timeval32 {
+ uint32_t tv_sec;
+ uint32_t tv_usec;
+};
+
+int
+linux_gettimeofday(struct thread *td, struct linux_gettimeofday_args *uap)
+{
+ struct timeval atv;
+ struct timeval32 atv32;
+ struct timezone rtz;
+ int error = 0;
+
+ if (uap->tp) {
+ microtime(&atv);
+ atv32.tv_sec = atv.tv_sec;
+ atv32.tv_usec = atv.tv_usec;
+ error = copyout(&atv32, uap->tp, sizeof(atv32));
+ }
+ if (error == 0 && uap->tzp != NULL) {
+ rtz.tz_minuteswest = tz_minuteswest;
+ rtz.tz_dsttime = tz_dsttime;
+ error = copyout(&rtz, uap->tzp, sizeof(rtz));
+ }
+ return (error);
+}
+
+int
+linux_settimeofday(struct thread *td, struct linux_settimeofday_args *uap)
+{
+ struct timeval32 atv32;
+ struct timeval atv, *tvp;
+ struct timezone atz, *tzp;
+ int error;
+
+ if (uap->tp) {
+ error = copyin(uap->tp, &atv32, sizeof(atv32));
+ if (error)
+ return (error);
+ atv.tv_sec = atv32.tv_sec;
+ atv.tv_usec = atv32.tv_usec;
+ tvp = &atv;
+ } else
+ tvp = NULL;
+ if (uap->tzp) {
+ error = copyin(uap->tzp, &atz, sizeof(atz));
+ if (error)
+ return (error);
+ tzp = &atz;
+ } else
+ tzp = NULL;
+ return (kern_settimeofday(td, tvp, tzp));
+}
+int
+linux_set_cloned_tls(struct thread *td, void *desc)
+{
+ struct l_user_desc info;
+ int idx, error;
+
+ error = copyin(desc, &info, sizeof(struct l_user_desc));
+ if (error) {
+ printf(LMSG("copyin failed!"));
+ } else {
+ idx = info.entry_number;
+
+ /*
+ * looks like we're getting the idx we returned
+ * in the set_thread_area() syscall
+ */
+ if (idx != 6 && idx != 3) {
+ printf(LMSG("resetting idx!"));
+ idx = 3;
+ }
+
+ /* this doesnt happen in practice */
+ if (idx == 6) {
+ /* we might copy out the entry_number as 3 */
+ info.entry_number = 3;
+ error = copyout(&info, desc, sizeof(struct l_user_desc));
+ if (error)
+ printf(LMSG("copyout failed!"));
+ }
+
+#ifdef DEBUG
+ if (ldebug(clone))
+ printf("Segment created in clone\n");
+#endif
+ }
+
+ return (error);
+}
+
+int
+linux_set_upcall_kse(struct thread *td, register_t stack)
+{
+
+ if (stack)
+ td->td_frame->tf_r13 = stack;
+
+ /*
+ * The newly created Linux thread returns
+ * to the user space by the same path that a parent do.
+ */
+ td->td_frame->tf_r0 = 0;
+ return (0);
+}
+
+#define STACK_SIZE (2 * 1024 * 1024)
+#define GUARD_SIZE (4 * PAGE_SIZE)
+
+int
+linux_mmap2(struct thread *td, struct linux_mmap2_args *args)
+{
+
+#ifdef DEBUG
+ if (ldebug(mmap2))
+ printf(ARGS(mmap2, "%p, %d, %d, 0x%08x, %d, %d"),
+ (void *)args->addr, args->len, args->prot,
+ args->flags, args->fd, args->pgoff);
+#endif
+
+ return (linux_mmap_common(td, args->addr, args->len, args->prot,
+ args->flags, args->fd, (uint64_t)(uint32_t)args->pgoff *
+ PAGE_SIZE));
+}
+
+static int
+linux_mmap_common(struct thread *td, l_uintptr_t addr, l_size_t len, l_int prot,
+ l_int flags, l_int fd, l_loff_t pos)
+{
+ struct proc *p = td->td_proc;
+ struct mmap_args /* {
+ caddr_t addr;
+ size_t len;
+ int prot;
+ int flags;
+ int fd;
+ long pad;
+ off_t pos;
+ } */ bsd_args;
+ int error;
+ struct file *fp;
+ cap_rights_t rights;
+
+ error = 0;
+ bsd_args.flags = 0;
+ fp = NULL;
+
+ /*
+ * Linux mmap(2):
+ * You must specify exactly one of MAP_SHARED and MAP_PRIVATE
+ */
+ if (!((flags & LINUX_MAP_SHARED) ^ (flags & LINUX_MAP_PRIVATE)))
+ return (EINVAL);
+
+ if (flags & LINUX_MAP_SHARED)
+ bsd_args.flags |= MAP_SHARED;
+ if (flags & LINUX_MAP_PRIVATE)
+ bsd_args.flags |= MAP_PRIVATE;
+ if (flags & LINUX_MAP_FIXED)
+ bsd_args.flags |= MAP_FIXED;
+ if (flags & LINUX_MAP_ANON) {
+ /* Enforce pos to be on page boundary, then ignore. */
+ if ((pos & PAGE_MASK) != 0)
+ return (EINVAL);
+ pos = 0;
+ bsd_args.flags |= MAP_ANON;
+ } else
+ bsd_args.flags |= MAP_NOSYNC;
+ if (flags & LINUX_MAP_GROWSDOWN)
+ bsd_args.flags |= MAP_STACK;
+
+ /*
+ * PROT_READ, PROT_WRITE, or PROT_EXEC implies PROT_READ and PROT_EXEC
+ * on Linux/i386. We do this to ensure maximum compatibility.
+ * Linux/ia64 does the same in i386 emulation mode.
+ */
+ bsd_args.prot = prot;
+ if (bsd_args.prot & (PROT_READ | PROT_WRITE | PROT_EXEC))
+ bsd_args.prot |= PROT_READ | PROT_EXEC;
+
+ /* Linux does not check file descriptor when MAP_ANONYMOUS is set. */
+ bsd_args.fd = (bsd_args.flags & MAP_ANON) ? -1 : fd;
+ if (bsd_args.fd != -1) {
+ /*
+ * Linux follows Solaris mmap(2) description:
+ * The file descriptor fildes is opened with
+ * read permission, regardless of the
+ * protection options specified.
+ *
+ * Checking just CAP_MMAP is fine here, since the real work
+ * is done in the FreeBSD mmap().
+ */
+
+ error = fget(td, bsd_args.fd,
+ cap_rights_init(&rights, CAP_MMAP), &fp);
+ if (error != 0)
+ return (error);
+ if (fp->f_type != DTYPE_VNODE) {
+ fdrop(fp, td);
+ return (EINVAL);
+ }
+
+ /* Linux mmap() just fails for O_WRONLY files */
+ if (!(fp->f_flag & FREAD)) {
+ fdrop(fp, td);
+ return (EACCES);
+ }
+
+ fdrop(fp, td);
+ }
+
+ if (flags & LINUX_MAP_GROWSDOWN) {
+ /*
+ * The Linux MAP_GROWSDOWN option does not limit auto
+ * growth of the region. Linux mmap with this option
+ * takes as addr the inital BOS, and as len, the initial
+ * region size. It can then grow down from addr without
+ * limit. However, linux threads has an implicit internal
+ * limit to stack size of STACK_SIZE. Its just not
+ * enforced explicitly in linux. But, here we impose
+ * a limit of (STACK_SIZE - GUARD_SIZE) on the stack
+ * region, since we can do this with our mmap.
+ *
+ * Our mmap with MAP_STACK takes addr as the maximum
+ * downsize limit on BOS, and as len the max size of
+ * the region. It them maps the top SGROWSIZ bytes,
+ * and auto grows the region down, up to the limit
+ * in addr.
+ *
+ * If we don't use the MAP_STACK option, the effect
+ * of this code is to allocate a stack region of a
+ * fixed size of (STACK_SIZE - GUARD_SIZE).
+ */
+
+ if ((caddr_t)PTRIN(addr) + len > p->p_vmspace->vm_maxsaddr) {
+ /*
+ * Some linux apps will attempt to mmap
+ * thread stacks near the top of their
+ * address space. If their TOS is greater
+ * than vm_maxsaddr, vm_map_growstack()
+ * will confuse the thread stack with the
+ * process stack and deliver a SEGV if they
+ * attempt to grow the thread stack past their
+ * current stacksize rlimit. To avoid this,
+ * adjust vm_maxsaddr upwards to reflect
+ * the current stacksize rlimit rather
+ * than the maximum possible stacksize.
+ * It would be better to adjust the
+ * mmap'ed region, but some apps do not check
+ * mmap's return value.
+ */
+ PROC_LOCK(p);
+ p->p_vmspace->vm_maxsaddr = (char *)USRSTACK -
+ lim_cur_proc(p, RLIMIT_STACK);
+ PROC_UNLOCK(p);
+ }
+
+ /*
+ * This gives us our maximum stack size and a new BOS.
+ * If we're using VM_STACK, then mmap will just map
+ * the top SGROWSIZ bytes, and let the stack grow down
+ * to the limit at BOS. If we're not using VM_STACK
+ * we map the full stack, since we don't have a way
+ * to autogrow it.
+ */
+ if (len > STACK_SIZE - GUARD_SIZE) {
+ bsd_args.addr = (caddr_t)PTRIN(addr);
+ bsd_args.len = len;
+ } else {
+ bsd_args.addr = (caddr_t)PTRIN(addr) -
+ (STACK_SIZE - GUARD_SIZE - len);
+ bsd_args.len = STACK_SIZE - GUARD_SIZE;
+ }
+ } else {
+ bsd_args.addr = (caddr_t)PTRIN(addr);
+ bsd_args.len = len;
+ }
+ bsd_args.pos = pos;
+
+#ifdef DEBUG
+ if (ldebug(mmap))
+ printf("-> %s(%p, %d, %d, 0x%08x, %d, 0x%x)\n",
+ __func__,
+ (void *)bsd_args.addr, bsd_args.len, bsd_args.prot,
+ bsd_args.flags, bsd_args.fd, (int)bsd_args.pos);
+#endif
+ error = sys_mmap(td, &bsd_args);
+#ifdef DEBUG
+ if (ldebug(mmap))
+ printf("-> %s() return: 0x%x (0x%08x)\n",
+ __func__, error, (u_int)td->td_retval[0]);
+#endif
+ return (error);
+}
+
+int
+linux_mprotect(struct thread *td, struct linux_mprotect_args *uap)
+{
+ struct mprotect_args bsd_args;
+
+ bsd_args.addr = uap->addr;
+ bsd_args.len = uap->len;
+ bsd_args.prot = uap->prot;
+ if (bsd_args.prot & (PROT_READ | PROT_WRITE | PROT_EXEC))
+ bsd_args.prot |= PROT_READ | PROT_EXEC;
+ return (sys_mprotect(td, &bsd_args));
+}
+
+int
+linux_sigaction(struct thread *td, struct linux_sigaction_args *args)
+{
+ l_osigaction_t osa;
+ l_sigaction_t act, oact;
+ int error;
+
+#ifdef DEBUG
+ if (ldebug(sigaction))
+ printf(ARGS(sigaction, "%d, %p, %p"),
+ args->sig, (void *)args->nsa, (void *)args->osa);
+#endif
+
+ if (args->nsa != NULL) {
+ error = copyin(args->nsa, &osa, sizeof(l_osigaction_t));
+ if (error)
+ return (error);
+ act.lsa_handler = osa.lsa_handler;
+ act.lsa_flags = osa.lsa_flags;
+ act.lsa_restorer = osa.lsa_restorer;
+ LINUX_SIGEMPTYSET(act.lsa_mask);
+ act.lsa_mask.__mask = osa.lsa_mask;
+ }
+
+ error = linux_do_sigaction(td, args->sig, args->nsa ? &act : NULL,
+ args->osa ? &oact : NULL);
+
+ if (args->osa != NULL && !error) {
+ osa.lsa_handler = oact.lsa_handler;
+ osa.lsa_flags = oact.lsa_flags;
+ osa.lsa_restorer = oact.lsa_restorer;
+ osa.lsa_mask = oact.lsa_mask.__mask;
+ error = copyout(&osa, args->osa, sizeof(l_osigaction_t));
+ }
+
+ return (error);
+}
+
+/*
+ * Linux has two extra args, restart and oldmask. We dont use these,
+ * but it seems that "restart" is actually a context pointer that
+ * enables the signal to happen with a different register set.
+ */
+int
+linux_sigsuspend(struct thread *td, struct linux_sigsuspend_args *args)
+{
+ sigset_t sigmask;
+ l_sigset_t mask;
+
+#ifdef DEBUG
+ if (ldebug(sigsuspend))
+ printf(ARGS(sigsuspend, "%08lx"), (unsigned long)args->mask);
+#endif
+
+ LINUX_SIGEMPTYSET(mask);
+ mask.__mask = args->mask;
+ linux_to_bsd_sigset(&mask, &sigmask);
+ return (kern_sigsuspend(td, sigmask));
+}
+
+int
+linux_rt_sigsuspend(struct thread *td, struct linux_rt_sigsuspend_args *uap)
+{
+ l_sigset_t lmask;
+ sigset_t sigmask;
+ int error;
+
+#ifdef DEBUG
+ if (ldebug(rt_sigsuspend))
+ printf(ARGS(rt_sigsuspend, "%p, %d"),
+ (void *)uap->newset, uap->sigsetsize);
+#endif
+
+ if (uap->sigsetsize != sizeof(l_sigset_t))
+ return (EINVAL);
+
+ error = copyin(uap->newset, &lmask, sizeof(l_sigset_t));
+ if (error)
+ return (error);
+
+ linux_to_bsd_sigset(&lmask, &sigmask);
+ return (kern_sigsuspend(td, sigmask));
+}
+
+int
+linux_pause(struct thread *td, struct linux_pause_args *args)
+{
+ struct proc *p = td->td_proc;
+ sigset_t sigmask;
+
+#ifdef DEBUG
+ if (ldebug(pause))
+ printf(ARGS(pause, ""));
+#endif
+
+ PROC_LOCK(p);
+ sigmask = td->td_sigmask;
+ PROC_UNLOCK(p);
+ return (kern_sigsuspend(td, sigmask));
+}
+
+int
+linux_sigaltstack(struct thread *td, struct linux_sigaltstack_args *uap)
+{
+ stack_t ss, oss;
+ l_stack_t lss;
+ int error;
+
+#ifdef DEBUG
+ if (ldebug(sigaltstack))
+ printf(ARGS(sigaltstack, "%p, %p"), uap->uss, uap->uoss);
+#endif
+
+ if (uap->uss != NULL) {
+ error = copyin(uap->uss, &lss, sizeof(l_stack_t));
+ if (error)
+ return (error);
+
+ ss.ss_sp = (char*)lss.ss_sp;
+ ss.ss_size = (__size_t)lss.ss_size;
+ ss.ss_flags = linux_to_bsd_sigaltstack(lss.ss_flags);
+ }
+ error = kern_sigaltstack(td, (uap->uss != NULL) ? &ss : NULL,
+ (uap->uoss != NULL) ? &oss : NULL);
+ if (!error && uap->uoss != NULL) {
+ lss.ss_sp = oss.ss_sp;
+ lss.ss_size = (l_size_t )oss.ss_size;
+ lss.ss_flags = bsd_to_linux_sigaltstack(oss.ss_flags);
+ error = copyout(&lss, uap->uoss, sizeof(l_stack_t));
+ }
+ return (error);
+}
+
+int
+linux_ftruncate64(struct thread *td, struct linux_ftruncate64_args *args)
+{
+ struct ftruncate_args sa;
+
+#ifdef DEBUG
+ if (ldebug(ftruncate64))
+ printf(ARGS(ftruncate64, "%u, %jd"), args->fd,
+ (intmax_t)args->length);
+#endif
+
+ sa.fd = args->fd;
+ sa.length = args->length;
+ return sys_ftruncate(td, &sa);
+}
+
+/* XXX: this wont work with module - convert it */
+int
+linux_mq_open(struct thread *td, struct linux_mq_open_args *args)
+{
+#ifdef P1003_1B_MQUEUE
+ return sys_kmq_open(td, (struct kmq_open_args *) args);
+#else
+ return (ENOSYS);
+#endif
+}
+
+int
+linux_mq_unlink(struct thread *td, struct linux_mq_unlink_args *args)
+{
+#ifdef P1003_1B_MQUEUE
+ return sys_kmq_unlink(td, (struct kmq_unlink_args *) args);
+#else
+ return (ENOSYS);
+#endif
+}
+
+int
+linux_mq_timedsend(struct thread *td, struct linux_mq_timedsend_args *args)
+{
+#ifdef P1003_1B_MQUEUE
+ return sys_kmq_timedsend(td, (struct kmq_timedsend_args *) args);
+#else
+ return (ENOSYS);
+#endif
+}
+
+int
+linux_mq_timedreceive(struct thread *td, struct linux_mq_timedreceive_args *args)
+{
+#ifdef P1003_1B_MQUEUE
+ return sys_kmq_timedreceive(td, (struct kmq_timedreceive_args *) args);
+#else
+ return (ENOSYS);
+#endif
+}
+
+int
+linux_mq_notify(struct thread *td, struct linux_mq_notify_args *args)
+{
+#ifdef P1003_1B_MQUEUE
+ return sys_kmq_notify(td, (struct kmq_notify_args *) args);
+#else
+ return (ENOSYS);
+#endif
+}
+
+int
+linux_mq_getsetattr(struct thread *td, struct linux_mq_getsetattr_args *args)
+{
+#ifdef P1003_1B_MQUEUE
+ return sys_kmq_setattr(td, (struct kmq_setattr_args *) args);
+#else
+ return (ENOSYS);
+#endif
+}
+
+int
+linux_set_tls(struct thread *td, struct linux_set_tls_args *args)
+{
+
+#if __ARM_ARCH >= 6
+ td->td_pcb->pcb_regs.sf_tpidrurw = (register_t)args->tls;
+#else
+ td->td_md.md_tp = (register_t)args->tls;
+#endif
+ // Do it ??
+ set_tls(args->tls);
+
+ return (0);
+}
+
+uint32_t
+linux_get_tls(struct thread *td)
+{
+
+#if __ARM_ARCH >= 6
+ return (td->td_pcb->pcb_regs.sf_tpidrurw);
+#else
+ return (td->td_md.md_tp);
+#endif
+}
Index: sys/arm/linux/linux_sysvec.c
===================================================================
--- /dev/null
+++ sys/arm/linux/linux_sysvec.c
@@ -0,0 +1,1129 @@
+/*-
+ * Copyright (c) 1994-1996 Søren Schmidt
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer
+ * in this position and unchanged.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/exec.h>
+#include <sys/fcntl.h>
+#include <sys/imgact.h>
+#include <sys/imgact_aout.h>
+#include <sys/imgact_elf.h>
+#include <sys/kernel.h>
+#include <sys/lock.h>
+#include <sys/malloc.h>
+#include <sys/module.h>
+#include <sys/mutex.h>
+#include <sys/proc.h>
+#include <sys/signalvar.h>
+#include <sys/syscallsubr.h>
+#include <sys/sysctl.h>
+#include <sys/sysent.h>
+#include <sys/sysproto.h>
+#include <sys/vnode.h>
+#include <sys/eventhandler.h>
+
+#include <vm/vm.h>
+#include <vm/pmap.h>
+#include <vm/vm_extern.h>
+#include <vm/vm_map.h>
+#include <vm/vm_object.h>
+#include <vm/vm_page.h>
+#include <vm/vm_param.h>
+
+#include <machine/cpu.h>
+#include <machine/md_var.h>
+#include <machine/pcb.h>
+
+#include <arm/linux/linux.h>
+#include <arm/linux/linux_proto.h>
+#include <compat/linux/linux_emul.h>
+#include <compat/linux/linux_futex.h>
+#include <compat/linux/linux_ioctl.h>
+#include <compat/linux/linux_mib.h>
+#include <compat/linux/linux_misc.h>
+#include <compat/linux/linux_signal.h>
+#include <compat/linux/linux_util.h>
+#include <compat/linux/linux_vdso.h>
+
+extern const char *linux_syscallnames[];
+
+#define ARM_NR_BASE 400
+
+MODULE_VERSION(linux, 1);
+
+#if BYTE_ORDER == LITTLE_ENDIAN
+#define SHELLMAGIC 0x2123 /* #! */
+#else
+#define SHELLMAGIC 0x2321
+#endif
+
+#if defined(DEBUG)
+SYSCTL_PROC(_compat_linux, OID_AUTO, debug,
+ CTLTYPE_STRING | CTLFLAG_RW,
+ 0, 0, linux_sysctl_debug, "A",
+ "Linux debugging control");
+#endif
+
+/*
+ * Allow the sendsig functions to use the ldebug() facility
+ * even though they are not syscalls themselves. Map them
+ * to syscall 0. This is slightly less bogus than using
+ * ldebug(sigreturn).
+ */
+#define LINUX_SYS_linux_rt_sendsig 0
+#define LINUX_SYS_linux_sendsig 0
+
+#define LINUX_PS_STRINGS (LINUX_USRSTACK - sizeof(struct ps_strings))
+
+static int linux_szsigcode;
+static vm_object_t linux_shared_page_obj;
+static char *linux_shared_page_mapping;
+extern char _binary_linux_locore_o_start;
+extern char _binary_linux_locore_o_end;
+
+extern struct sysent linux_sysent[LINUX_SYS_MAXSYSCALL];
+
+SET_DECLARE(linux_ioctl_handler_set, struct linux_ioctl_handler);
+
+static int linux_fixup(register_t **stack_base,
+ struct image_params *iparams);
+static int elf_linux_fixup(register_t **stack_base,
+ struct image_params *iparams);
+static void linux_sendsig(sig_t catcher, ksiginfo_t *ksi, sigset_t *mask);
+static void exec_linux_setregs(struct thread *td,
+ struct image_params *imgp, u_long stack);
+static register_t *linux_copyout_strings(struct image_params *imgp);
+static boolean_t linux_trans_osrel(const Elf_Note *note, int32_t *osrel);
+static void linux_vdso_install(void *param);
+static void linux_vdso_deinstall(void *param);
+
+static int linux_szplatform;
+const char *linux_kplatform;
+
+static eventhandler_tag linux_exit_tag;
+static eventhandler_tag linux_exec_tag;
+static eventhandler_tag linux_thread_dtor_tag;
+
+/*
+ * Linux syscalls return negative errno's, we do positive and map them
+ * Reference:
+ * FreeBSD: src/sys/sys/errno.h
+ * Linux: linux-2.6.17.8/include/asm-generic/errno-base.h
+ * linux-2.6.17.8/include/asm-generic/errno.h
+ */
+static int bsd_to_linux_errno[ELAST + 1] = {
+ -0, -1, -2, -3, -4, -5, -6, -7, -8, -9,
+ -10, -35, -12, -13, -14, -15, -16, -17, -18, -19,
+ -20, -21, -22, -23, -24, -25, -26, -27, -28, -29,
+ -30, -31, -32, -33, -34, -11,-115,-114, -88, -89,
+ -90, -91, -92, -93, -94, -95, -96, -97, -98, -99,
+ -100,-101,-102,-103,-104,-105,-106,-107,-108,-109,
+ -110,-111, -40, -36,-112,-113, -39, -11, -87,-122,
+ -116, -66, -6, -6, -6, -6, -6, -37, -38, -9,
+ -6, -6, -43, -42, -75,-125, -84, -95, -16, -74,
+ -72, -67, -71
+};
+
+#define LINUX_T_UNKNOWN 255
+static int _bsd_to_linux_trapcode[] = {
+ LINUX_T_UNKNOWN, /* 0 */
+ 6, /* 1 T_PRIVINFLT */
+ LINUX_T_UNKNOWN, /* 2 */
+ 3, /* 3 T_BPTFLT */
+ LINUX_T_UNKNOWN, /* 4 */
+ LINUX_T_UNKNOWN, /* 5 */
+ 16, /* 6 T_ARITHTRAP */
+ 254, /* 7 T_ASTFLT */
+ LINUX_T_UNKNOWN, /* 8 */
+ 13, /* 9 T_PROTFLT */
+ 1, /* 10 T_TRCTRAP */
+ LINUX_T_UNKNOWN, /* 11 */
+ 14, /* 12 T_PAGEFLT */
+ LINUX_T_UNKNOWN, /* 13 */
+ 17, /* 14 T_ALIGNFLT */
+ LINUX_T_UNKNOWN, /* 15 */
+ LINUX_T_UNKNOWN, /* 16 */
+ LINUX_T_UNKNOWN, /* 17 */
+ 0, /* 18 T_DIVIDE */
+ 2, /* 19 T_NMI */
+ 4, /* 20 T_OFLOW */
+ 5, /* 21 T_BOUND */
+ 7, /* 22 T_DNA */
+ 8, /* 23 T_DOUBLEFLT */
+ 9, /* 24 T_FPOPFLT */
+ 10, /* 25 T_TSSFLT */
+ 11, /* 26 T_SEGNPFLT */
+ 12, /* 27 T_STKFLT */
+ 18, /* 28 T_MCHK */
+ 19, /* 29 T_XMMFLT */
+ 15 /* 30 T_RESERVED */
+};
+#define bsd_to_linux_trapcode(code) \
+ ((code)<nitems(_bsd_to_linux_trapcode)? \
+ _bsd_to_linux_trapcode[(code)]: \
+ LINUX_T_UNKNOWN)
+
+LINUX_VDSO_SYM_INTPTR(linux_sigcode);
+LINUX_VDSO_SYM_INTPTR(linux_rt_sigcode);
+LINUX_VDSO_SYM_INTPTR(linux_vsyscall);
+
+static int
+translate_traps(int signal, int trap_code)
+{
+
+ return (signal);
+}
+
+static int
+linux_fixup(register_t **stack_base, struct image_params *imgp)
+{
+ register_t *argv, *envp;
+
+ argv = *stack_base;
+ envp = *stack_base + (imgp->args->argc + 1);
+ (*stack_base)--;
+ suword(*stack_base, (intptr_t)(void *)envp);
+ (*stack_base)--;
+ suword(*stack_base, (intptr_t)(void *)argv);
+ (*stack_base)--;
+ suword(*stack_base, imgp->args->argc);
+ return (0);
+}
+
+static int
+elf_linux_fixup(register_t **stack_base, struct image_params *imgp)
+{
+ struct proc *p;
+ Elf32_Auxargs *args;
+ Elf32_Addr *uplatform;
+ struct ps_strings *arginfo;
+ register_t *pos;
+
+ KASSERT(curthread->td_proc == imgp->proc,
+ ("unsafe elf_linux_fixup(), should be curproc"));
+
+ p = imgp->proc;
+ arginfo = (struct ps_strings *)p->p_sysent->sv_psstrings;
+ uplatform = (Elf32_Addr *)((caddr_t)arginfo - linux_szplatform);
+ args = (Elf32_Auxargs *)imgp->auxargs;
+ pos = *stack_base + (imgp->args->argc + imgp->args->envc + 2);
+
+ AUXARGS_ENTRY(pos, LINUX_AT_SYSINFO_EHDR,
+ imgp->proc->p_sysent->sv_shared_page_base);
+ AUXARGS_ENTRY(pos, LINUX_AT_SYSINFO, linux_vsyscall);
+
+ /*
+ * Do not export AT_CLKTCK when emulating Linux kernel prior to 2.4.0,
+ * as it has appeared in the 2.4.0-rc7 first time.
+ * Being exported, AT_CLKTCK is returned by sysconf(_SC_CLK_TCK),
+ * glibc falls back to the hard-coded CLK_TCK value when aux entry
+ * is not present.
+ * Also see linux_times() implementation.
+ */
+ if (linux_kernver(curthread) >= LINUX_KERNVER_2004000)
+ AUXARGS_ENTRY(pos, LINUX_AT_CLKTCK, stclohz);
+ AUXARGS_ENTRY(pos, AT_PHDR, args->phdr);
+ AUXARGS_ENTRY(pos, AT_PHENT, args->phent);
+ AUXARGS_ENTRY(pos, AT_PHNUM, args->phnum);
+ AUXARGS_ENTRY(pos, AT_PAGESZ, args->pagesz);
+ AUXARGS_ENTRY(pos, AT_FLAGS, args->flags);
+ AUXARGS_ENTRY(pos, AT_ENTRY, args->entry);
+ AUXARGS_ENTRY(pos, AT_BASE, args->base);
+ AUXARGS_ENTRY(pos, LINUX_AT_SECURE, 0);
+ AUXARGS_ENTRY(pos, AT_UID, imgp->proc->p_ucred->cr_ruid);
+ AUXARGS_ENTRY(pos, AT_EUID, imgp->proc->p_ucred->cr_svuid);
+ AUXARGS_ENTRY(pos, AT_GID, imgp->proc->p_ucred->cr_rgid);
+ AUXARGS_ENTRY(pos, AT_EGID, imgp->proc->p_ucred->cr_svgid);
+ AUXARGS_ENTRY(pos, LINUX_AT_PLATFORM, PTROUT(uplatform));
+ AUXARGS_ENTRY(pos, LINUX_AT_RANDOM, imgp->canary);
+ if (imgp->execpathp != 0)
+ AUXARGS_ENTRY(pos, LINUX_AT_EXECFN, imgp->execpathp);
+ if (args->execfd != -1)
+ AUXARGS_ENTRY(pos, AT_EXECFD, args->execfd);
+ AUXARGS_ENTRY(pos, AT_NULL, 0);
+
+ free(imgp->auxargs, M_TEMP);
+ imgp->auxargs = NULL;
+
+ (*stack_base)--;
+ suword(*stack_base, (register_t)imgp->args->argc);
+ return (0);
+}
+
+/*
+ * Copied from kern/kern_exec.c
+ */
+static register_t *
+linux_copyout_strings(struct image_params *imgp)
+{
+ int argc, envc;
+ char **vectp;
+ char *stringp, *destp;
+ register_t *stack_base;
+ struct ps_strings *arginfo;
+ char canary[LINUX_AT_RANDOM_LEN];
+ size_t execpath_len;
+ struct proc *p;
+
+ /*
+ * Calculate string base and vector table pointers.
+ */
+ p = imgp->proc;
+ if (imgp->execpath != NULL && imgp->auxargs != NULL)
+ execpath_len = strlen(imgp->execpath) + 1;
+ else
+ execpath_len = 0;
+ arginfo = (struct ps_strings *)p->p_sysent->sv_psstrings;
+ destp = (caddr_t)arginfo - SPARE_USRSPACE - linux_szplatform -
+ roundup(sizeof(canary), sizeof(char *)) -
+ roundup(execpath_len, sizeof(char *)) -
+ roundup(ARG_MAX - imgp->args->stringspace, sizeof(char *));
+
+ /*
+ * install LINUX_PLATFORM
+ */
+ copyout(linux_kplatform, ((caddr_t)arginfo - linux_szplatform),
+ linux_szplatform);
+
+ if (execpath_len != 0) {
+ imgp->execpathp = (uintptr_t)arginfo -
+ linux_szplatform - execpath_len;
+ copyout(imgp->execpath, (void *)imgp->execpathp, execpath_len);
+ }
+
+ /*
+ * Prepare the canary for SSP.
+ */
+ arc4rand(canary, sizeof(canary), 0);
+ imgp->canary = (uintptr_t)arginfo - linux_szplatform -
+ roundup(execpath_len, sizeof(char *)) -
+ roundup(sizeof(canary), sizeof(char *));
+ copyout(canary, (void *)imgp->canary, sizeof(canary));
+
+ /*
+ * If we have a valid auxargs ptr, prepare some room
+ * on the stack.
+ */
+ if (imgp->auxargs) {
+ /*
+ * 'AT_COUNT*2' is size for the ELF Auxargs data. This is for
+ * lower compatibility.
+ */
+ imgp->auxarg_size = (imgp->auxarg_size) ? imgp->auxarg_size :
+ (LINUX_AT_COUNT * 2);
+ /*
+ * The '+ 2' is for the null pointers at the end of each of
+ * the arg and env vector sets,and imgp->auxarg_size is room
+ * for argument of Runtime loader.
+ */
+ vectp = (char **)(destp - (imgp->args->argc +
+ imgp->args->envc + 2 + imgp->auxarg_size) * sizeof(char *));
+ } else {
+ /*
+ * The '+ 2' is for the null pointers at the end of each of
+ * the arg and env vector sets
+ */
+ vectp = (char **)(destp - (imgp->args->argc + imgp->args->envc + 2) *
+ sizeof(char *));
+ }
+
+ /*
+ * vectp also becomes our initial stack base
+ */
+ stack_base = (register_t *)vectp;
+
+ stringp = imgp->args->begin_argv;
+ argc = imgp->args->argc;
+ envc = imgp->args->envc;
+
+ /*
+ * Copy out strings - arguments and environment.
+ */
+ copyout(stringp, destp, ARG_MAX - imgp->args->stringspace);
+
+ /*
+ * Fill in "ps_strings" struct for ps, w, etc.
+ */
+ suword(&arginfo->ps_argvstr, (long)(intptr_t)vectp);
+ suword(&arginfo->ps_nargvstr, argc);
+
+ /*
+ * Fill in argument portion of vector table.
+ */
+ for (; argc > 0; --argc) {
+ suword(vectp++, (long)(intptr_t)destp);
+ while (*stringp++ != 0)
+ destp++;
+ destp++;
+ }
+
+ /* a null vector table pointer separates the argp's from the envp's */
+ suword(vectp++, 0);
+
+ suword(&arginfo->ps_envstr, (long)(intptr_t)vectp);
+ suword(&arginfo->ps_nenvstr, envc);
+
+ /*
+ * Fill in environment portion of vector table.
+ */
+ for (; envc > 0; --envc) {
+ suword(vectp++, (long)(intptr_t)destp);
+ while (*stringp++ != 0)
+ destp++;
+ destp++;
+ }
+
+ /* end of vector table is a null pointer */
+ suword(vectp, 0);
+
+ return (stack_base);
+}
+
+static void
+linux_rt_sendsig(sig_t catcher, ksiginfo_t *ksi, sigset_t *mask)
+{
+ struct thread *td = curthread;
+ struct proc *p = td->td_proc;
+ struct sigacts *psp;
+ struct trapframe *regs;
+ struct l_rt_sigframe *fp, frame;
+ int sig, code;
+ int oonstack;
+
+ sig = ksi->ksi_signo;
+ code = ksi->ksi_code;
+ PROC_LOCK_ASSERT(p, MA_OWNED);
+ psp = p->p_sigacts;
+ mtx_assert(&psp->ps_mtx, MA_OWNED);
+ regs = td->td_frame;
+ oonstack = sigonstack(regs->tf_r13);
+
+#ifdef DEBUG
+ if (ldebug(rt_sendsig))
+ printf(ARGS(rt_sendsig, "%p, %d, %p, %u"),
+ catcher, sig, (void*)mask, code);
+#endif
+ /*
+ * Allocate space for the signal handler context.
+ */
+ if ((td->td_pflags & TDP_ALTSTACK) && !oonstack &&
+ SIGISMEMBER(psp->ps_sigonstack, sig)) {
+ fp = (struct l_rt_sigframe *)((uintptr_t)td->td_sigstk.ss_sp +
+ td->td_sigstk.ss_size - sizeof(struct l_rt_sigframe));
+ } else
+ fp = (struct l_rt_sigframe *)regs->tf_r13 - 1;
+ mtx_unlock(&psp->ps_mtx);
+
+ /*
+ * Build the argument list for the signal handler.
+ */
+ sig = bsd_to_linux_signal(sig);
+
+ bzero(&frame, sizeof(frame));
+
+ frame.sf_handler = (l_handler_t)catcher;
+ frame.sf_sig = sig;
+ frame.sf_siginfo = &fp->sf_si;
+ frame.sf_ucontext = &fp->sf_sc;
+
+ /* Fill in POSIX parts */
+ ksiginfo_to_lsiginfo(ksi, &frame.sf_si, sig);
+
+ /*
+ * Build the signal context to be used by sigreturn.
+ */
+ frame.sf_sc.uc_flags = 0; /* XXX ??? */
+ frame.sf_sc.uc_link = (void*)NULL; /* XXX ??? */
+
+ frame.sf_sc.uc_stack.ss_sp = td->td_sigstk.ss_sp;
+ frame.sf_sc.uc_stack.ss_size = td->td_sigstk.ss_size;
+ frame.sf_sc.uc_stack.ss_flags = (td->td_pflags & TDP_ALTSTACK)
+ ? ((oonstack) ? LINUX_SS_ONSTACK : 0) : LINUX_SS_DISABLE;
+ PROC_UNLOCK(p);
+
+ bsd_to_linux_sigset(mask, &frame.sf_sc.uc_sigmask);
+
+ frame.sf_sc.uc_mcontext.oldmask = frame.sf_sc.uc_sigmask.__mask;
+ frame.sf_sc.uc_mcontext.fault_address = (register_t)ksi->ksi_addr;
+ frame.sf_sc.uc_mcontext.arm_r0 = regs->tf_r0;
+ frame.sf_sc.uc_mcontext.arm_r1 = regs->tf_r1;
+ frame.sf_sc.uc_mcontext.arm_r2 = regs->tf_r2;
+ frame.sf_sc.uc_mcontext.arm_r3 = regs->tf_r3;
+ frame.sf_sc.uc_mcontext.arm_r4 = regs->tf_r4;
+ frame.sf_sc.uc_mcontext.arm_r5 = regs->tf_r5;
+ frame.sf_sc.uc_mcontext.arm_r6 = regs->tf_r6;
+ frame.sf_sc.uc_mcontext.arm_r7 = regs->tf_r7;
+ frame.sf_sc.uc_mcontext.arm_r8 = regs->tf_r8;
+ frame.sf_sc.uc_mcontext.arm_r9 = regs->tf_r9;
+ frame.sf_sc.uc_mcontext.arm_r10 = regs->tf_r10;
+ frame.sf_sc.uc_mcontext.arm_fp = regs->tf_r11;
+ frame.sf_sc.uc_mcontext.arm_ip = regs->tf_r12;
+ frame.sf_sc.uc_mcontext.arm_sp = regs->tf_r13;
+ frame.sf_sc.uc_mcontext.arm_lr = regs->tf_r14;
+ frame.sf_sc.uc_mcontext.arm_pc = regs->tf_r15;
+ frame.sf_sc.uc_mcontext.arm_cpsr = regs->tf_spsr;
+ frame.sf_sc.uc_mcontext.error_code = 0;
+ frame.sf_sc.uc_mcontext.trap_no = bsd_to_linux_trapcode(code);
+
+#ifdef DEBUG
+ if (ldebug(rt_sendsig))
+ printf(LMSG("rt_sendsig flags: 0x%x, sp: %p, ss: 0x%x, mask: 0x%x"),
+ frame.sf_sc.uc_stack.ss_flags, td->td_sigstk.ss_sp,
+ td->td_sigstk.ss_size, (unsigned int)frame.sf_sc.uc_mcontext.arm_cpsr);
+#endif
+
+ if (copyout(&frame, fp, sizeof(frame)) != 0) {
+ /*
+ * Process has trashed its stack; give it an illegal
+ * instruction to halt it in its tracks.
+ */
+#ifdef DEBUG
+ if (ldebug(rt_sendsig))
+ printf(LMSG("rt_sendsig: bad stack %p, oonstack=%x"),
+ fp, oonstack);
+#endif
+ PROC_LOCK(p);
+ sigexit(td, SIGILL);
+ }
+
+ /*
+ * Build context to run handler in.
+ */
+ regs->tf_r13 = (int)fp;
+ regs->tf_r15 = linux_rt_sigcode;
+ PROC_LOCK(p);
+ mtx_lock(&psp->ps_mtx);
+}
+
+
+/*
+ * Send an interrupt to process.
+ *
+ * Stack is set up to allow sigcode stored
+ * in u. to call routine, followed by kcall
+ * to sigreturn routine below. After sigreturn
+ * resets the signal mask, the stack, and the
+ * frame pointer, it returns to the user
+ * specified pc, psl.
+ */
+static void
+linux_sendsig(sig_t catcher, ksiginfo_t *ksi, sigset_t *mask)
+{
+ struct thread *td = curthread;
+ struct proc *p = td->td_proc;
+ struct sigacts *psp;
+ struct trapframe *regs;
+ struct l_sigframe *fp, frame;
+ l_sigset_t lmask;
+ int sig, code;
+ int oonstack;
+
+ PROC_LOCK_ASSERT(p, MA_OWNED);
+ psp = p->p_sigacts;
+ sig = ksi->ksi_signo;
+ code = ksi->ksi_code;
+ mtx_assert(&psp->ps_mtx, MA_OWNED);
+ if (SIGISMEMBER(psp->ps_siginfo, sig)) {
+ /* Signal handler installed with SA_SIGINFO. */
+ linux_rt_sendsig(catcher, ksi, mask);
+ return;
+ }
+ regs = td->td_frame;
+ oonstack = sigonstack(regs->tf_r13);
+
+#ifdef DEBUG
+ if (ldebug(sendsig))
+ printf(ARGS(sendsig, "%p, %d, %p, %u"),
+ catcher, sig, (void*)mask, code);
+#endif
+
+ /*
+ * Allocate space for the signal handler context.
+ */
+ if ((td->td_pflags & TDP_ALTSTACK) && !oonstack &&
+ SIGISMEMBER(psp->ps_sigonstack, sig)) {
+ fp = (struct l_sigframe *)((uintptr_t)td->td_sigstk.ss_sp +
+ td->td_sigstk.ss_size - sizeof(struct l_sigframe));
+ } else
+ fp = (struct l_sigframe *)regs->tf_r13 - 1;
+ mtx_unlock(&psp->ps_mtx);
+ PROC_UNLOCK(p);
+
+ /*
+ * Build the argument list for the signal handler.
+ */
+ sig = bsd_to_linux_signal(sig);
+
+ bzero(&frame, sizeof(frame));
+
+ frame.sf_handler = (l_handler_t)catcher;
+ frame.sf_sig = sig;
+
+ bsd_to_linux_sigset(mask, &lmask);
+
+ /*
+ * Build the signal context to be used by sigreturn.
+ */
+ frame.sf_sc.oldmask = lmask.__mask;
+ frame.sf_sc.fault_address = (register_t)ksi->ksi_addr;
+ frame.sf_sc.arm_r0 = regs->tf_r0;
+ frame.sf_sc.arm_r1 = regs->tf_r1;
+ frame.sf_sc.arm_r2 = regs->tf_r2;
+ frame.sf_sc.arm_r3 = regs->tf_r3;
+ frame.sf_sc.arm_r4 = regs->tf_r4;
+ frame.sf_sc.arm_r5 = regs->tf_r5;
+ frame.sf_sc.arm_r6 = regs->tf_r6;
+ frame.sf_sc.arm_r7 = regs->tf_r7;
+ frame.sf_sc.arm_r8 = regs->tf_r8;
+ frame.sf_sc.arm_r9 = regs->tf_r9;
+ frame.sf_sc.arm_r10 = regs->tf_r10;
+ frame.sf_sc.arm_fp = regs->tf_r11;
+ frame.sf_sc.arm_ip = regs->tf_r12;
+ frame.sf_sc.arm_sp = regs->tf_r13;
+ frame.sf_sc.arm_lr = regs->tf_r14;
+ frame.sf_sc.arm_pc = regs->tf_r15;
+ frame.sf_sc.arm_cpsr = regs->tf_spsr;
+ frame.sf_sc.error_code = 0;
+ frame.sf_sc.trap_no = bsd_to_linux_trapcode(code);
+
+ frame.sf_extramask[0] = lmask.__mask;
+
+ if (copyout(&frame, fp, sizeof(frame)) != 0) {
+ /*
+ * Process has trashed its stack; give it an illegal
+ * instruction to halt it in its tracks.
+ */
+ PROC_LOCK(p);
+ sigexit(td, SIGILL);
+ }
+
+ /*
+ * Build context to run handler in.
+ */
+ regs->tf_r13 = (int)fp;
+ regs->tf_r15 = linux_sigcode;
+ PROC_LOCK(p);
+ mtx_lock(&psp->ps_mtx);
+}
+
+/*
+ * System call to cleanup state after a signal
+ * has been taken. Reset signal mask and
+ * stack state from context left by sendsig (above).
+ * Return to previous pc and psl as specified by
+ * context left by sendsig. Check carefully to
+ * make sure that the user has not modified the
+ * psl to gain improper privileges or to cause
+ * a machine fault.
+ */
+int
+linux_sigreturn(struct thread *td, struct linux_sigreturn_args *args)
+{
+ struct l_sigframe frame;
+ struct trapframe *regs;
+ l_sigset_t lmask;
+ sigset_t bmask;
+
+ regs = td->td_frame;
+
+#ifdef DEBUG
+ if (ldebug(sigreturn))
+ printf(ARGS(sigreturn, "%p"), (void *)args->sfp);
+#endif
+ /*
+ * The trampoline code hands us the sigframe.
+ * It is unsafe to keep track of it ourselves, in the event that a
+ * program jumps out of a signal handler.
+ */
+ if (copyin(args->sfp, &frame, sizeof(frame)) != 0)
+ return (EFAULT);
+
+ lmask.__mask = frame.sf_sc.oldmask;
+ linux_to_bsd_sigset(&lmask, &bmask);
+ kern_sigprocmask(td, SIG_SETMASK, &bmask, NULL, 0);
+
+ /*
+ * Restore signal context.
+ */
+ /* %gs was restored by the trampoline. */
+ regs->tf_r0 = frame.sf_sc.arm_r0 ;
+ regs->tf_r1 = frame.sf_sc.arm_r1 ;
+ regs->tf_r2 = frame.sf_sc.arm_r2 ;
+ regs->tf_r3 = frame.sf_sc.arm_r3 ;
+ regs->tf_r4 = frame.sf_sc.arm_r4 ;
+ regs->tf_r5 = frame.sf_sc.arm_r5 ;
+ regs->tf_r6 = frame.sf_sc.arm_r6 ;
+ regs->tf_r7 = frame.sf_sc.arm_r7 ;
+ regs->tf_r8 = frame.sf_sc.arm_r8 ;
+ regs->tf_r9 = frame.sf_sc.arm_r9 ;
+ regs->tf_r10 = frame.sf_sc.arm_r10 ;
+ regs->tf_r11 = frame.sf_sc.arm_fp ;
+ regs->tf_r12 = frame.sf_sc.arm_ip ;
+ regs->tf_r13 = frame.sf_sc.arm_sp ;
+ regs->tf_r14 = frame.sf_sc.arm_lr ;
+ regs->tf_r15 = frame.sf_sc.arm_pc ;
+ regs->tf_spsr = frame.sf_sc.arm_cpsr;
+
+ return (EJUSTRETURN);
+}
+
+/*
+ * System call to cleanup state after a signal
+ * has been taken. Reset signal mask and
+ * stack state from context left by rt_sendsig (above).
+ * Return to previous pc and psl as specified by
+ * context left by sendsig. Check carefully to
+ * make sure that the user has not modified the
+ * psl to gain improper privileges or to cause
+ * a machine fault.
+ */
+int
+linux_rt_sigreturn(struct thread *td, struct linux_rt_sigreturn_args *args)
+{
+ struct l_ucontext uc;
+ struct l_sigcontext *context;
+ sigset_t bmask;
+ l_stack_t *lss;
+ stack_t ss;
+ struct trapframe *regs;
+
+ regs = td->td_frame;
+
+#ifdef DEBUG
+ if (ldebug(rt_sigreturn))
+ printf(ARGS(rt_sigreturn, "%p"), (void *)args->ucp);
+#endif
+ /*
+ * The trampoline code hands us the ucontext.
+ * It is unsafe to keep track of it ourselves, in the event that a
+ * program jumps out of a signal handler.
+ */
+ if (copyin(args->ucp, &uc, sizeof(uc)) != 0)
+ return (EFAULT);
+
+ context = &uc.uc_mcontext;
+
+ linux_to_bsd_sigset(&uc.uc_sigmask, &bmask);
+ kern_sigprocmask(td, SIG_SETMASK, &bmask, NULL, 0);
+
+ /*
+ * Restore signal context
+ */
+ /* %gs was restored by the trampoline. */
+ regs->tf_r0 = context->arm_r0 ;
+ regs->tf_r1 = context->arm_r1 ;
+ regs->tf_r2 = context->arm_r2 ;
+ regs->tf_r3 = context->arm_r3 ;
+ regs->tf_r4 = context->arm_r4 ;
+ regs->tf_r5 = context->arm_r5 ;
+ regs->tf_r6 = context->arm_r6 ;
+ regs->tf_r7 = context->arm_r7 ;
+ regs->tf_r8 = context->arm_r8 ;
+ regs->tf_r9 = context->arm_r9 ;
+ regs->tf_r10 = context->arm_r10 ;
+ regs->tf_r11 = context->arm_fp ;
+ regs->tf_r12 = context->arm_ip ;
+ regs->tf_r13 = context->arm_sp ;
+ regs->tf_r14 = context->arm_lr ;
+ regs->tf_r15 = context->arm_pc ;
+ regs->tf_spsr = context->arm_cpsr;
+
+ /*
+ * call sigaltstack & ignore results..
+ */
+ lss = &uc.uc_stack;
+ ss.ss_sp = (char*)lss->ss_sp;
+ ss.ss_size = lss->ss_size;
+ ss.ss_flags = linux_to_bsd_sigaltstack(lss->ss_flags);
+
+#ifdef DEBUG
+ if (ldebug(rt_sigreturn))
+ printf(LMSG("rt_sigret flags: 0x%x, sp: %p, ss: 0x%x, mask: 0x%x"),
+ ss.ss_flags, ss.ss_sp, ss.ss_size, (unsigned int)context->arm_cpsr);
+#endif
+ (void)kern_sigaltstack(td, &ss, NULL);
+
+ return (EJUSTRETURN);
+}
+
+static int
+linux_fetch_syscall_args(struct thread *td, struct syscall_args *sa)
+{
+ struct proc *p;
+ struct trapframe *frame;
+
+ p = td->td_proc;
+ frame = td->td_frame;
+
+ sa->code = frame->tf_r7;
+ sa->args[0] = frame->tf_r0;
+ sa->args[1] = frame->tf_r1;
+ sa->args[2] = frame->tf_r2;
+ sa->args[3] = frame->tf_r3;
+ sa->args[4] = frame->tf_r4;
+ sa->args[5] = frame->tf_r5; /* Unconfirmed */
+
+ /*
+ * ARM syscall
+ * First ARM syscall in syscalls.master is @ ARM_NR_BASE
+ */
+ if ((sa->code >> 16) == 0x0f)
+ {
+ sa->code &= 0xffff;
+ sa->code += ARM_NR_BASE;
+ }
+
+ if (sa->code >= p->p_sysent->sv_size)
+ /* nosys */
+ sa->callp = &p->p_sysent->sv_table[p->p_sysent->sv_size - 1];
+ else
+ sa->callp = &p->p_sysent->sv_table[sa->code];
+ sa->narg = sa->callp->sy_narg;
+
+ td->td_retval[0] = 0;
+ td->td_retval[1] = frame->tf_r1;
+
+ return (0);
+}
+
+/*
+ * If a linux binary is exec'ing something, try this image activator
+ * first. We override standard shell script execution in order to
+ * be able to modify the interpreter path. We only do this if a linux
+ * binary is doing the exec, so we do not create an EXEC module for it.
+ */
+static int exec_linux_imgact_try(struct image_params *iparams);
+
+static int
+exec_linux_imgact_try(struct image_params *imgp)
+{
+ const char *head = (const char *)imgp->image_header;
+ char *rpath;
+ int error = -1;
+
+ /*
+ * The interpreter for shell scripts run from a linux binary needs
+ * to be located in /compat/linux if possible in order to recursively
+ * maintain linux path emulation.
+ */
+ if (((const short *)head)[0] == SHELLMAGIC) {
+ /*
+ * Run our normal shell image activator. If it succeeds attempt
+ * to use the alternate path for the interpreter. If an alternate
+ * path is found, use our stringspace to store it.
+ */
+ if ((error = exec_shell_imgact(imgp)) == 0) {
+ linux_emul_convpath(FIRST_THREAD_IN_PROC(imgp->proc),
+ imgp->interpreter_name, UIO_SYSSPACE, &rpath, 0, AT_FDCWD);
+ if (rpath != NULL)
+ imgp->args->fname_buf =
+ imgp->interpreter_name = rpath;
+ }
+ }
+ return (error);
+}
+
+/*
+ * exec_setregs may initialize some registers differently than Linux
+ * does, thus potentially confusing Linux binaries. If necessary, we
+ * override the exec_setregs default(s) here.
+ */
+static void
+exec_linux_setregs(struct thread *td, struct image_params *imgp, u_long stack)
+{
+
+ exec_setregs(td, imgp, stack);
+}
+
+static void
+linux_get_machine(const char **dst)
+{
+
+ *dst = "arm";
+}
+
+struct sysentvec linux_sysvec = {
+ .sv_size = LINUX_SYS_MAXSYSCALL,
+ .sv_table = linux_sysent,
+ .sv_mask = 0,
+ .sv_errsize = ELAST + 1,
+ .sv_errtbl = bsd_to_linux_errno,
+ .sv_transtrap = translate_traps,
+ .sv_fixup = linux_fixup,
+ .sv_sendsig = linux_sendsig,
+ .sv_sigcode = &_binary_linux_locore_o_start,
+ .sv_szsigcode = &linux_szsigcode,
+ .sv_name = "Linux a.out",
+ .sv_coredump = NULL,
+ .sv_imgact_try = exec_linux_imgact_try,
+ .sv_minsigstksz = LINUX_MINSIGSTKSZ,
+ .sv_pagesize = PAGE_SIZE,
+ .sv_minuser = VM_MIN_ADDRESS,
+ .sv_maxuser = VM_MAXUSER_ADDRESS,
+ .sv_usrstack = LINUX_USRSTACK,
+ .sv_psstrings = PS_STRINGS,
+ .sv_stackprot = VM_PROT_ALL,
+ .sv_copyout_strings = exec_copyout_strings,
+ .sv_setregs = exec_linux_setregs,
+ .sv_fixlimit = NULL,
+ .sv_maxssiz = NULL,
+ .sv_flags = SV_ABI_LINUX | SV_AOUT | SV_IA32 | SV_ILP32,
+ .sv_set_syscall_retval = cpu_set_syscall_retval,
+ .sv_fetch_syscall_args = linux_fetch_syscall_args,
+ .sv_syscallnames = linux_syscallnames,
+ .sv_shared_page_base = LINUX_SHAREDPAGE,
+ .sv_shared_page_len = PAGE_SIZE,
+ .sv_schedtail = linux_schedtail,
+ .sv_thread_detach = linux_thread_detach,
+ .sv_trap = NULL,
+};
+INIT_SYSENTVEC(aout_sysvec, &linux_sysvec);
+
+struct sysentvec elf_linux_sysvec = {
+ .sv_size = LINUX_SYS_MAXSYSCALL,
+ .sv_table = linux_sysent,
+ .sv_mask = 0,
+ .sv_errsize = ELAST + 1,
+ .sv_errtbl = bsd_to_linux_errno,
+ .sv_transtrap = translate_traps,
+ .sv_fixup = elf_linux_fixup,
+ .sv_sendsig = linux_sendsig,
+ .sv_sigcode = &_binary_linux_locore_o_start,
+ .sv_szsigcode = &linux_szsigcode,
+ .sv_name = "Linux ELF",
+ .sv_coredump = elf32_coredump,
+ .sv_imgact_try = exec_linux_imgact_try,
+ .sv_minsigstksz = LINUX_MINSIGSTKSZ,
+ .sv_pagesize = PAGE_SIZE,
+ .sv_minuser = VM_MIN_ADDRESS,
+ .sv_maxuser = VM_MAXUSER_ADDRESS,
+ .sv_usrstack = LINUX_USRSTACK,
+ .sv_psstrings = LINUX_PS_STRINGS,
+ .sv_stackprot = VM_PROT_ALL,
+ .sv_copyout_strings = linux_copyout_strings,
+ .sv_setregs = exec_linux_setregs,
+ .sv_fixlimit = NULL,
+ .sv_maxssiz = NULL,
+ .sv_flags = SV_ABI_LINUX | SV_IA32 | SV_ILP32 | SV_SHP,
+ .sv_set_syscall_retval = cpu_set_syscall_retval,
+ .sv_fetch_syscall_args = linux_fetch_syscall_args,
+ .sv_syscallnames = linux_syscallnames,
+ .sv_shared_page_base = LINUX_SHAREDPAGE,
+ .sv_shared_page_len = PAGE_SIZE,
+ .sv_schedtail = linux_schedtail,
+ .sv_thread_detach = linux_thread_detach,
+ .sv_trap = NULL,
+};
+
+static void
+linux_vdso_install(void *param)
+{
+
+ linux_szsigcode = (&_binary_linux_locore_o_end -
+ &_binary_linux_locore_o_start);
+
+ if (linux_szsigcode > elf_linux_sysvec.sv_shared_page_len)
+ panic("Linux invalid vdso size\n");
+
+ __elfN(linux_vdso_fixup)(&elf_linux_sysvec);
+
+ linux_shared_page_obj = __elfN(linux_shared_page_init)
+ (&linux_shared_page_mapping);
+
+ __elfN(linux_vdso_reloc)(&elf_linux_sysvec, LINUX_SHAREDPAGE);
+
+ bcopy(elf_linux_sysvec.sv_sigcode, linux_shared_page_mapping,
+ linux_szsigcode);
+ elf_linux_sysvec.sv_shared_page_obj = linux_shared_page_obj;
+}
+SYSINIT(elf_linux_vdso_init, SI_SUB_EXEC, SI_ORDER_ANY,
+ (sysinit_cfunc_t)linux_vdso_install, NULL);
+
+static void
+linux_vdso_deinstall(void *param)
+{
+
+ __elfN(linux_shared_page_fini)(linux_shared_page_obj);
+};
+SYSUNINIT(elf_linux_vdso_uninit, SI_SUB_EXEC, SI_ORDER_FIRST,
+ (sysinit_cfunc_t)linux_vdso_deinstall, NULL);
+
+static char GNU_ABI_VENDOR[] = "GNU";
+static int GNULINUX_ABI_DESC = 0;
+
+static boolean_t
+linux_trans_osrel(const Elf_Note *note, int32_t *osrel)
+{
+ const Elf32_Word *desc;
+ uintptr_t p;
+
+ p = (uintptr_t)(note + 1);
+ p += roundup2(note->n_namesz, sizeof(Elf32_Addr));
+
+ desc = (const Elf32_Word *)p;
+ if (desc[0] != GNULINUX_ABI_DESC)
+ return (FALSE);
+
+ /*
+ * For linux we encode osrel as follows (see linux_mib.c):
+ * VVVMMMIII (version, major, minor), see linux_mib.c.
+ */
+ *osrel = desc[1] * 1000000 + desc[2] * 1000 + desc[3];
+
+ return (TRUE);
+}
+
+static Elf_Brandnote linux_brandnote = {
+ .hdr.n_namesz = sizeof(GNU_ABI_VENDOR),
+ .hdr.n_descsz = 16, /* XXX at least 16 */
+ .hdr.n_type = 1,
+ .vendor = GNU_ABI_VENDOR,
+ .flags = BN_TRANSLATE_OSREL,
+ .trans_osrel = linux_trans_osrel
+};
+
+static Elf32_Brandinfo linux_brand = {
+ .brand = ELFOSABI_LINUX,
+ .machine = EM_ARM,
+ .compat_3_brand = "Linux",
+ .emul_path = "/compat/linux",
+ .interp_path = "/lib/ld-linux.so.1",
+ .sysvec = &elf_linux_sysvec,
+ .interp_newpath = NULL,
+ .brand_note = &linux_brandnote,
+ .flags = BI_CAN_EXEC_DYN | BI_BRAND_NOTE
+};
+
+static Elf32_Brandinfo linux_glibc2brand = {
+ .brand = ELFOSABI_LINUX,
+ .machine = EM_ARM,
+ .compat_3_brand = "Linux",
+ .emul_path = "/compat/linux",
+ .interp_path = "/lib/ld-linux.so.2",
+ .sysvec = &elf_linux_sysvec,
+ .interp_newpath = NULL,
+ .brand_note = &linux_brandnote,
+ .flags = BI_CAN_EXEC_DYN | BI_BRAND_NOTE
+};
+
+static Elf32_Brandinfo linux_uclibcbrand = {
+ .brand = ELFOSABI_LINUX,
+ .machine = EM_ARM,
+ .compat_3_brand = "Linux",
+ .emul_path = "/compat/linux",
+ .interp_path = "/lib/ld-uClibc.so.0",
+ .sysvec = &elf_linux_sysvec,
+ .interp_newpath = NULL,
+ .brand_note = &linux_brandnote,
+ .flags = BI_CAN_EXEC_DYN | BI_BRAND_NOTE
+};
+
+Elf32_Brandinfo *linux_brandlist[] = {
+ &linux_brand,
+ &linux_glibc2brand,
+ &linux_uclibcbrand,
+ NULL
+};
+
+static int
+linux_elf_modevent(module_t mod, int type, void *data)
+{
+ Elf32_Brandinfo **brandinfo;
+ int error;
+ struct linux_ioctl_handler **lihp;
+
+ error = 0;
+
+ switch(type) {
+ case MOD_LOAD:
+ for (brandinfo = &linux_brandlist[0]; *brandinfo != NULL;
+ ++brandinfo)
+ if (elf32_insert_brand_entry(*brandinfo) < 0)
+ error = EINVAL;
+ if (error == 0) {
+ SET_FOREACH(lihp, linux_ioctl_handler_set)
+ linux_ioctl_register_handler(*lihp);
+ LIST_INIT(&futex_list);
+ mtx_init(&futex_mtx, "ftllk", NULL, MTX_DEF);
+ linux_exit_tag = EVENTHANDLER_REGISTER(process_exit, linux_proc_exit,
+ NULL, 1000);
+ linux_exec_tag = EVENTHANDLER_REGISTER(process_exec, linux_proc_exec,
+ NULL, 1000);
+ linux_thread_dtor_tag = EVENTHANDLER_REGISTER(thread_dtor,
+ linux_thread_dtor, NULL, EVENTHANDLER_PRI_ANY);
+ linux_get_machine(&linux_kplatform);
+ linux_szplatform = roundup(strlen(linux_kplatform) + 1,
+ sizeof(char *));
+ linux_osd_jail_register();
+ stclohz = (stathz ? stathz : hz);
+ if (bootverbose)
+ printf("Linux ELF exec handler installed\n");
+ } else
+ printf("cannot insert Linux ELF brand handler\n");
+ break;
+ case MOD_UNLOAD:
+ for (brandinfo = &linux_brandlist[0]; *brandinfo != NULL;
+ ++brandinfo)
+ if (elf32_brand_inuse(*brandinfo))
+ error = EBUSY;
+ if (error == 0) {
+ for (brandinfo = &linux_brandlist[0];
+ *brandinfo != NULL; ++brandinfo)
+ if (elf32_remove_brand_entry(*brandinfo) < 0)
+ error = EINVAL;
+ }
+ if (error == 0) {
+ SET_FOREACH(lihp, linux_ioctl_handler_set)
+ linux_ioctl_unregister_handler(*lihp);
+ mtx_destroy(&futex_mtx);
+ EVENTHANDLER_DEREGISTER(process_exit, linux_exit_tag);
+ EVENTHANDLER_DEREGISTER(process_exec, linux_exec_tag);
+ EVENTHANDLER_DEREGISTER(thread_dtor, linux_thread_dtor_tag);
+ linux_osd_jail_deregister();
+ if (bootverbose)
+ printf("Linux ELF exec handler removed\n");
+ } else
+ printf("Could not deinstall ELF interpreter entry\n");
+ break;
+ default:
+ return (EOPNOTSUPP);
+ }
+ return (error);
+}
+
+static moduledata_t linux_elf_mod = {
+ "linuxelf",
+ linux_elf_modevent,
+ 0
+};
+
+DECLARE_MODULE_TIED(linuxelf, linux_elf_mod, SI_SUB_EXEC, SI_ORDER_ANY);
+FEATURE(linux, "Linux 32bit support");
Index: sys/arm/linux/linux_vdso.lds.s
===================================================================
--- /dev/null
+++ sys/arm/linux/linux_vdso.lds.s
@@ -0,0 +1,67 @@
+/*
+ * Linker script for 32-bit vDSO.
+ * Copied from Linux kernel arch/arm/vdso/vdso.lds.S
+ *
+ * $FreeBSD$
+ */
+
+SECTIONS
+{
+ PROVIDE(_start = .) ;
+
+ . = SIZEOF_HEADERS ;
+
+ .hash : { *(.hash) } :text
+ .gnu.hash : { *(.gnu.hash) }
+ .dynsym : { *(.dynsym) }
+ .dynstr : { *(.dynstr) }
+ .gnu.version : { *(.gnu.version) }
+ .gnu.version_d : { *(.gnu.version_d) }
+ .gnu.version_r : { *(.gnu.version_r) }
+
+ .note : { *(.note.*) } :text :note
+
+
+ .eh_frame_hdr : { *(.eh_frame_hdr) } :text :eh_frame_hdr
+ .eh_frame : { KEEP (*(.eh_frame)) } :text
+
+ .dynamic : { *(.dynamic) } :text :dynamic
+
+ .rodata : { *(.rodata*) } :text
+
+ .text : { *(.text*) } :text =0xe7f001f2
+
+ .got : { *(.got) }
+ .rel.plt : { *(.rel.plt) }
+
+ /DISCARD/ : {
+ *(.note.GNU-stack)
+ *(.data .data.* .gnu.linkonce.d.* .sdata*)
+ *(.bss .sbss .dynbss .dynsbss)
+ }
+}
+
+ /*
+ * We must supply the ELF program headers explicitly to get just one
+ * PT_LOAD segment, and set the flags explicitly to make segments read-only.
+ */
+PHDRS
+{
+ text PT_LOAD FLAGS(5) FILEHDR PHDRS ; /* PF_R|PF_X */
+ dynamic PT_DYNAMIC FLAGS(4) ; /* PF_R */
+ note PT_NOTE FLAGS(4) ; /* PF_R */
+ eh_frame_hdr PT_GNU_EH_FRAME ;
+}
+
+ENTRY(linux_vsyscall);
+
+VERSION
+{
+ LINUX_2.6 {
+ global:
+ linux_vsyscall;
+ linux_sigcode;
+ linux_rt_sigcode;
+ local: * ;
+ } ;
+ }

File Metadata

Mime Type
text/plain
Expires
Mon, Nov 18, 1:33 AM (20 h, 42 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
14688066
Default Alt Text
D7974.diff (75 KB)

Event Timeline