mirror of
https://git.freebsd.org/ports.git
synced 2025-06-24 14:10:30 -04:00
8355 lines
236 KiB
Text
8355 lines
236 KiB
Text
#diff --git a/Makefile b/Makefile
|
|
#index 5fa0f1d..55e151e 100644
|
|
#--- a/Makefile
|
|
#+++ b/Makefile
|
|
#@@ -65,7 +65,8 @@ CLANG_CFLAGS_AS+= -no-integrated-as
|
|
#
|
|
# .if ${PORT_OPTIONS:MX86_TARGETS}
|
|
# .if ${PORT_OPTIONS:MBSD_USER}
|
|
#-CONFIGURE_ARGS+= --target-list=i386-softmmu,x86_64-softmmu,i386-bsd-user,x86_64-bsd-user,sparc-bsd-user,sparc64-bsd-user,arm-bsd-user
|
|
#+#CONFIGURE_ARGS+= --target-list=i386-softmmu,x86_64-softmmu,i386-bsd-user,x86_64-bsd-user,sparc-bsd-user,sparc64-bsd-user,arm-bsd-user,armeb-bsd-user,mips-bsd-user,mipsel-bsd-user
|
|
#+CONFIGURE_ARGS+= --target-list=arm-bsd-user,armeb-bsd-user,mips-bsd-user,mipsel-bsd-user,mips64-bsd-user
|
|
# .else
|
|
# CONFIGURE_ARGS+= --target-list=i386-softmmu,x86_64-softmmu
|
|
# .endif
|
|
#@@ -106,6 +107,8 @@ CONFIGURE_ARGS+= --prefix=${PREFIX} --cc=${CC} --enable-docs \
|
|
# --disable-linux-user --disable-linux-aio \
|
|
# --disable-kvm --disable-xen \
|
|
# --smbd=${LOCALBASE}/sbin/smbd \
|
|
#+ --enable-debug \
|
|
#+ --enable-debug-info \
|
|
# --extra-cflags=-I${WRKSRC}\ -I${LOCALBASE}/include\ -DPREFIX=\\\"${PREFIX}\\\"
|
|
#
|
|
# .if empty(PORT_OPTIONS:MSDL)
|
|
diff --git a/bsd-user/arm/target_signal.h b/bsd-user/arm/target_signal.h
|
|
index 1b644cc..19cc188 100644
|
|
--- a/bsd-user/arm/target_signal.h
|
|
+++ b/bsd-user/arm/target_signal.h
|
|
@@ -3,17 +3,12 @@
|
|
|
|
#include "cpu.h"
|
|
|
|
-/* this struct defines a stack used during syscall handling */
|
|
-
|
|
-typedef struct target_sigaltstack {
|
|
- abi_ulong ss_sp;
|
|
- abi_long ss_flags;
|
|
- abi_ulong ss_size;
|
|
-} target_stack_t;
|
|
-
|
|
static inline abi_ulong get_sp_from_cpustate(CPUARMState *state)
|
|
{
|
|
return state->regs[13];
|
|
}
|
|
|
|
+#define TARGET_MINSIGSTKSZ (1024 * 4)
|
|
+#define TARGET_SIGSTKSZ (TARGET_MINSIGSTKSZ + 32768)
|
|
+
|
|
#endif /* TARGET_SIGNAL_H */
|
|
diff --git a/bsd-user/arm/target_vmparam.h b/bsd-user/arm/target_vmparam.h
|
|
new file mode 100644
|
|
index 0000000..0427244
|
|
--- /dev/null
|
|
+++ b/bsd-user/arm/target_vmparam.h
|
|
@@ -0,0 +1,28 @@
|
|
+#ifndef _TARGET_VMPARAM_H_
|
|
+#define _TARGET_VMPARAM_H_
|
|
+
|
|
+#if defined(__FreeBSD__)
|
|
+ /* KERNBASE - 512 MB */
|
|
+#define TARGET_VM_MAXUSER_ADDRESS (0xc0000000 - (512 * 1024 * 1024))
|
|
+#define TARGET_USRSTACK TARGET_VM_MAXUSER_ADDRESS
|
|
+
|
|
+struct target_ps_strings {
|
|
+ abi_ulong ps_argvstr;
|
|
+ uint32_t ps_nargvstr;
|
|
+ abi_ulong ps_envstr;
|
|
+ uint32_t ps_nenvstr;
|
|
+};
|
|
+
|
|
+#define TARGET_SPACE_USRSPACE 4096
|
|
+#define TARGET_ARG_MAX 262144
|
|
+
|
|
+#define TARGET_PS_STRINGS (TARGET_USRSTACK - sizeof(struct target_ps_strings))
|
|
+
|
|
+#define TARGET_SZSIGCODE 0
|
|
+
|
|
+#else
|
|
+
|
|
+#define TARGET_USRSTACK 0
|
|
+#endif
|
|
+
|
|
+#endif /* _TARGET_VMPARAM_H_ */
|
|
diff --git a/bsd-user/bsdload.c b/bsd-user/bsdload.c
|
|
index 2abc713..dcf6f66 100644
|
|
--- a/bsd-user/bsdload.c
|
|
+++ b/bsd-user/bsdload.c
|
|
@@ -53,7 +53,7 @@ static int count(char ** vec)
|
|
return(i);
|
|
}
|
|
|
|
-static int prepare_binprm(struct linux_binprm *bprm)
|
|
+static int prepare_binprm(struct bsd_binprm *bprm)
|
|
{
|
|
struct stat st;
|
|
int mode;
|
|
@@ -155,33 +155,33 @@ abi_ulong loader_build_argptr(int envc, int argc, abi_ulong sp,
|
|
}
|
|
|
|
int loader_exec(const char * filename, char ** argv, char ** envp,
|
|
- struct target_pt_regs * regs, struct image_info *infop)
|
|
+ struct target_pt_regs * regs, struct image_info *infop,
|
|
+ struct bsd_binprm *bprm)
|
|
{
|
|
- struct linux_binprm bprm;
|
|
int retval;
|
|
int i;
|
|
|
|
- bprm.p = TARGET_PAGE_SIZE*MAX_ARG_PAGES-sizeof(unsigned int);
|
|
+ bprm->p = TARGET_PAGE_SIZE*MAX_ARG_PAGES /*-sizeof(unsigned int) XXX */;
|
|
for (i=0 ; i<MAX_ARG_PAGES ; i++) /* clear page-table */
|
|
- bprm.page[i] = NULL;
|
|
+ bprm->page[i] = NULL;
|
|
retval = open(filename, O_RDONLY);
|
|
if (retval < 0)
|
|
return retval;
|
|
- bprm.fd = retval;
|
|
- bprm.filename = (char *)filename;
|
|
- bprm.argc = count(argv);
|
|
- bprm.argv = argv;
|
|
- bprm.envc = count(envp);
|
|
- bprm.envp = envp;
|
|
+ bprm->fd = retval;
|
|
+ bprm->filename = (char *)filename;
|
|
+ bprm->argc = count(argv);
|
|
+ bprm->argv = argv;
|
|
+ bprm->envc = count(envp);
|
|
+ bprm->envp = envp;
|
|
|
|
- retval = prepare_binprm(&bprm);
|
|
+ retval = prepare_binprm(bprm);
|
|
|
|
if(retval>=0) {
|
|
- if (bprm.buf[0] == 0x7f
|
|
- && bprm.buf[1] == 'E'
|
|
- && bprm.buf[2] == 'L'
|
|
- && bprm.buf[3] == 'F') {
|
|
- retval = load_elf_binary(&bprm,regs,infop);
|
|
+ if (bprm->buf[0] == 0x7f
|
|
+ && bprm->buf[1] == 'E'
|
|
+ && bprm->buf[2] == 'L'
|
|
+ && bprm->buf[3] == 'F') {
|
|
+ retval = load_elf_binary(bprm,regs,infop);
|
|
} else {
|
|
fprintf(stderr, "Unknown binary format\n");
|
|
return -1;
|
|
@@ -196,7 +196,7 @@ int loader_exec(const char * filename, char ** argv, char ** envp,
|
|
|
|
/* Something went wrong, return the inode and free the argument pages*/
|
|
for (i=0 ; i<MAX_ARG_PAGES ; i++) {
|
|
- g_free(bprm.page[i]);
|
|
+ g_free(bprm->page[i]);
|
|
}
|
|
return(retval);
|
|
}
|
|
diff --git a/bsd-user/elfload.c b/bsd-user/elfload.c
|
|
index 993dcf7..15cf3a6 100644
|
|
--- a/bsd-user/elfload.c
|
|
+++ b/bsd-user/elfload.c
|
|
@@ -9,6 +9,8 @@
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
|
|
+#include <sys/param.h>
|
|
+
|
|
#include "qemu.h"
|
|
#include "disas.h"
|
|
|
|
@@ -93,6 +95,7 @@ enum {
|
|
|
|
#ifdef TARGET_I386
|
|
|
|
+#ifndef __FreeBSD__
|
|
#define ELF_PLATFORM get_elf_platform()
|
|
|
|
static const char *get_elf_platform(void)
|
|
@@ -112,6 +115,7 @@ static uint32_t get_elf_hwcap(void)
|
|
{
|
|
return thread_env->cpuid_features;
|
|
}
|
|
+#endif /* ! __FreeBSD__ */
|
|
|
|
#ifdef TARGET_X86_64
|
|
#define ELF_START_MMAP 0x2aaaaab000ULL
|
|
@@ -378,13 +382,14 @@ static inline void init_thread(struct target_pt_regs *_regs, struct image_info *
|
|
|
|
#ifdef TARGET_MIPS
|
|
|
|
-#define ELF_START_MMAP 0x80000000
|
|
|
|
#define elf_check_arch(x) ( (x) == EM_MIPS )
|
|
|
|
-#ifdef TARGET_MIPS64
|
|
+#if defined(TARGET_MIPS64)
|
|
+#define ELF_START_MMAP 0x2aaaaab000ULL
|
|
#define ELF_CLASS ELFCLASS64
|
|
#else
|
|
+#define ELF_START_MMAP 0x80000000
|
|
#define ELF_CLASS ELFCLASS32
|
|
#endif
|
|
#ifdef TARGET_WORDS_BIGENDIAN
|
|
@@ -396,9 +401,10 @@ static inline void init_thread(struct target_pt_regs *_regs, struct image_info *
|
|
|
|
static inline void init_thread(struct target_pt_regs *regs, struct image_info *infop)
|
|
{
|
|
+
|
|
regs->cp0_status = 2 << CP0St_KSU;
|
|
- regs->cp0_epc = infop->entry;
|
|
- regs->regs[29] = infop->start_stack;
|
|
+ regs->regs[25] = regs->cp0_epc = infop->entry; /* t9 = pc = entry */
|
|
+ regs->regs[4] = regs->regs[29] = infop->start_stack; /* a0 = sp = start_stack */
|
|
}
|
|
|
|
#define USE_ELF_CORE_DUMP
|
|
@@ -576,30 +582,38 @@ static void bswap_ehdr(struct elfhdr *ehdr)
|
|
bswap16s(&ehdr->e_shstrndx); /* Section header string table index */
|
|
}
|
|
|
|
-static void bswap_phdr(struct elf_phdr *phdr)
|
|
+static void bswap_phdr(struct elf_phdr *phdr, int phnum)
|
|
{
|
|
- bswap32s(&phdr->p_type); /* Segment type */
|
|
- bswaptls(&phdr->p_offset); /* Segment file offset */
|
|
- bswaptls(&phdr->p_vaddr); /* Segment virtual address */
|
|
- bswaptls(&phdr->p_paddr); /* Segment physical address */
|
|
- bswaptls(&phdr->p_filesz); /* Segment size in file */
|
|
- bswaptls(&phdr->p_memsz); /* Segment size in memory */
|
|
- bswap32s(&phdr->p_flags); /* Segment flags */
|
|
- bswaptls(&phdr->p_align); /* Segment alignment */
|
|
+ int i;
|
|
+
|
|
+ for (i = 0; i < phnum; ++i, ++phdr) {
|
|
+ bswap32s(&phdr->p_type); /* Segment type */
|
|
+ bswap32s(&phdr->p_flags); /* Segment flags */
|
|
+ bswaptls(&phdr->p_offset); /* Segment file offset */
|
|
+ bswaptls(&phdr->p_vaddr); /* Segment virtual address */
|
|
+ bswaptls(&phdr->p_paddr); /* Segment physical address */
|
|
+ bswaptls(&phdr->p_filesz); /* Segment size in file */
|
|
+ bswaptls(&phdr->p_memsz); /* Segment size in memory */
|
|
+ bswaptls(&phdr->p_align); /* Segment alignment */
|
|
+ }
|
|
}
|
|
|
|
-static void bswap_shdr(struct elf_shdr *shdr)
|
|
+static void bswap_shdr(struct elf_shdr *shdr, int shnum)
|
|
{
|
|
- bswap32s(&shdr->sh_name);
|
|
- bswap32s(&shdr->sh_type);
|
|
- bswaptls(&shdr->sh_flags);
|
|
- bswaptls(&shdr->sh_addr);
|
|
- bswaptls(&shdr->sh_offset);
|
|
- bswaptls(&shdr->sh_size);
|
|
- bswap32s(&shdr->sh_link);
|
|
- bswap32s(&shdr->sh_info);
|
|
- bswaptls(&shdr->sh_addralign);
|
|
- bswaptls(&shdr->sh_entsize);
|
|
+ int i;
|
|
+
|
|
+ for (i = 0; i < shnum; ++i, ++shdr) {
|
|
+ bswap32s(&shdr->sh_name);
|
|
+ bswap32s(&shdr->sh_type);
|
|
+ bswaptls(&shdr->sh_flags);
|
|
+ bswaptls(&shdr->sh_addr);
|
|
+ bswaptls(&shdr->sh_offset);
|
|
+ bswaptls(&shdr->sh_size);
|
|
+ bswap32s(&shdr->sh_link);
|
|
+ bswap32s(&shdr->sh_info);
|
|
+ bswaptls(&shdr->sh_addralign);
|
|
+ bswaptls(&shdr->sh_entsize);
|
|
+ }
|
|
}
|
|
|
|
static void bswap_sym(struct elf_sym *sym)
|
|
@@ -609,7 +623,14 @@ static void bswap_sym(struct elf_sym *sym)
|
|
bswaptls(&sym->st_size);
|
|
bswap16s(&sym->st_shndx);
|
|
}
|
|
-#endif
|
|
+
|
|
+#else /* ! BSWAP_NEEDED */
|
|
+
|
|
+static inline void bswap_ehdr(struct elfhdr *ehdr) { }
|
|
+static inline void bswap_phdr(struct elf_phdr *phdr, int phnum) { }
|
|
+static inline void bswap_shdr(struct elf_shdr *shdr, int shnum) { }
|
|
+static inline void bswap_sym(struct elf_sym *sym) { }
|
|
+#endif /* ! BSWAP_NEEDED */
|
|
|
|
/*
|
|
* 'copy_elf_strings()' copies argument/envelope strings from user
|
|
@@ -666,7 +687,26 @@ static abi_ulong copy_elf_strings(int argc,char ** argv, void **page,
|
|
return p;
|
|
}
|
|
|
|
-static abi_ulong setup_arg_pages(abi_ulong p, struct linux_binprm *bprm,
|
|
+#if defined(TARGET_MIPS64)
|
|
+static inline int
|
|
+install_sigtramp(abi_ulong offset, unsigned sigf_uc, unsigned syscall)
|
|
+{
|
|
+ int i;
|
|
+ uint32_t sigtramp_code[] = {
|
|
+ 0x67A40000 + sigf_uc, /* daddu $a0, $sp, (sigf_uc) */
|
|
+ 0x24020000 + syscall, /* li $v0, (syscall) */
|
|
+ 0x0000000C, /* syscall */
|
|
+ 0x0000000D /* break */
|
|
+ };
|
|
+
|
|
+ for(i = 0; i < 4; i++)
|
|
+ tswap32s(&sigtramp_code[i]);
|
|
+
|
|
+ return (memcpy_to_target(offset, sigtramp_code, TARGET_SZSIGCODE));
|
|
+}
|
|
+#endif
|
|
+
|
|
+static abi_ulong setup_arg_pages(abi_ulong p, struct bsd_binprm *bprm,
|
|
struct image_info *info)
|
|
{
|
|
abi_ulong stack_base, size, error;
|
|
@@ -678,7 +718,13 @@ static abi_ulong setup_arg_pages(abi_ulong p, struct linux_binprm *bprm,
|
|
size = x86_stack_size;
|
|
if (size < MAX_ARG_PAGES*TARGET_PAGE_SIZE)
|
|
size = MAX_ARG_PAGES*TARGET_PAGE_SIZE;
|
|
- error = target_mmap(0,
|
|
+
|
|
+#ifdef TARGET_USRSTACK
|
|
+ stack_base = TARGET_USRSTACK - size;
|
|
+#else
|
|
+ stack_base = (abi_ulong)0;
|
|
+#endif
|
|
+ error = target_mmap(stack_base,
|
|
size + qemu_host_page_size,
|
|
PROT_READ | PROT_WRITE,
|
|
MAP_PRIVATE | MAP_ANON,
|
|
@@ -690,6 +736,113 @@ static abi_ulong setup_arg_pages(abi_ulong p, struct linux_binprm *bprm,
|
|
/* we reserve one extra page at the top of the stack as guard */
|
|
target_mprotect(error + size, qemu_host_page_size, PROT_NONE);
|
|
|
|
+#if defined(__FreeBSD__)
|
|
+ /*
|
|
+ * The inital FreeBSD stack looks like follows:
|
|
+ * (see kern/kern_exec.c exec_copyout_strings() )
|
|
+ *
|
|
+ * Hi Address -> char **ps_argvstr (struct ps_strings for ps, w, etc.)
|
|
+ * unsigned ps_nargvstr
|
|
+ * char **ps_envstr
|
|
+ * PS_STRINGS -> unsigned ps_nenvstr
|
|
+ *
|
|
+ * machine dependent sigcode (sv_sigcode of size
|
|
+ * sv_szsigcode)
|
|
+ *
|
|
+ * execpath (absolute image path for rtld)
|
|
+ *
|
|
+ * SSP Canary (sizeof(long) * 8)
|
|
+ *
|
|
+ * page sizes array (usually sizeof(u_long) )
|
|
+ *
|
|
+ * "destp" -> argv, env strings (up to 262144 bytes)
|
|
+ */
|
|
+
|
|
+ {
|
|
+ abi_ulong stack_hi_addr;
|
|
+ size_t execpath_len;
|
|
+ abi_ulong destp;
|
|
+ struct target_ps_strings ps_strs;
|
|
+ char canary[sizeof(abi_long) * 8];
|
|
+ char execpath[PATH_MAX];
|
|
+
|
|
+ stack_hi_addr = p = error + size;
|
|
+
|
|
+ /* Save some space for ps_strings. */
|
|
+ p -= sizeof(struct target_ps_strings);
|
|
+
|
|
+#if TARGET_SZSIGCODE > 0
|
|
+ /* Add machine depedent sigcode. */
|
|
+ p -= TARGET_SZSIGCODE;
|
|
+ /* XXX - check return value of memcpy_to_target() for failure */
|
|
+ install_sigtramp( p, (unsigned)offsetof(struct target_sigframe,
|
|
+ sf_uc), TARGET_FREEBSD_NR_sigreturn);
|
|
+#endif
|
|
+
|
|
+ /* Add execpath for rtld. */
|
|
+ if (strlen(bprm->filename)) {
|
|
+ /* XXX - check return value of realpath() */
|
|
+ realpath(bprm->filename, execpath);
|
|
+ execpath_len = strlen(execpath) + 1;
|
|
+ } else
|
|
+ execpath_len = 0;
|
|
+
|
|
+ if (execpath_len) {
|
|
+ p -= roundup(execpath_len, sizeof(abi_ulong));
|
|
+ /* XXX - check return value of memcpy_to_target() */
|
|
+ memcpy_to_target(p, execpath, execpath_len);
|
|
+ }
|
|
+
|
|
+ /* Add canary for SSP. */
|
|
+ arc4random_buf(canary, sizeof(canary));
|
|
+ p -= roundup(sizeof(canary), sizeof(abi_ulong));
|
|
+ /* XXX - check return value of memcpy_to_target(). */
|
|
+ memcpy_to_target(p, canary, sizeof(canary));
|
|
+
|
|
+ /* Add page sizes array. */
|
|
+ p -= sizeof(abi_ulong);
|
|
+ /* XXX - check return value of put_user_ual(). */
|
|
+ put_user_ual(TARGET_PAGE_SIZE, p);
|
|
+
|
|
+ p = destp = p - TARGET_SPACE_USRSPACE - TARGET_ARG_MAX;
|
|
+
|
|
+ /* XXX should check strlen(argv and envp strings) < TARGET_ARG_MAX */
|
|
+
|
|
+ /*
|
|
+ * Add argv strings. Note that the argv[] vectors are added by
|
|
+ * loader_build_argptr()
|
|
+ */
|
|
+ i = bprm->argc;
|
|
+ while (i-- > 0) {
|
|
+ size_t len = strlen(bprm->argv[i]) + 1;
|
|
+ /* XXX - check return value of memcpy_to_target(). */
|
|
+ memcpy_to_target(destp, bprm->argv[i], len);
|
|
+ destp += len;
|
|
+ }
|
|
+ ps_strs.ps_argvstr = tswapl(destp);
|
|
+ ps_strs.ps_nargvstr = tswap32(bprm->argc);
|
|
+
|
|
+ /*
|
|
+ * Add env strings. Note that the envp[] vectors are added by
|
|
+ * loader_build_argptr().
|
|
+ */
|
|
+ i = bprm->envc;
|
|
+ while(i-- > 0) {
|
|
+ size_t len = strlen(bprm->envp[i]) + 1;
|
|
+ /* XXX - check return value of memcpy_to_target(). */
|
|
+ memcpy_to_target(destp, bprm->envp[i], len);
|
|
+ destp += len;
|
|
+ }
|
|
+ ps_strs.ps_envstr = tswapl(destp);
|
|
+ ps_strs.ps_nenvstr = tswap32(bprm->envc);
|
|
+
|
|
+ /* XXX - check return value of memcpy_to_target(). */
|
|
+ memcpy_to_target(stack_hi_addr - sizeof(ps_strs), &ps_strs,
|
|
+ sizeof(ps_strs));
|
|
+ }
|
|
+
|
|
+#else
|
|
+
|
|
stack_base = error + size - MAX_ARG_PAGES*TARGET_PAGE_SIZE;
|
|
p += stack_base;
|
|
|
|
@@ -702,6 +855,8 @@ static abi_ulong setup_arg_pages(abi_ulong p, struct linux_binprm *bprm,
|
|
}
|
|
stack_base += TARGET_PAGE_SIZE;
|
|
}
|
|
+#endif
|
|
+
|
|
return p;
|
|
}
|
|
|
|
@@ -769,11 +924,14 @@ static abi_ulong create_elf_tables(abi_ulong p, int argc, int envc,
|
|
{
|
|
abi_ulong sp;
|
|
int size;
|
|
+#ifndef __FreeBSD__
|
|
abi_ulong u_platform;
|
|
const char *k_platform;
|
|
+#endif
|
|
const int n = sizeof(elf_addr_t);
|
|
|
|
sp = p;
|
|
+#ifndef __FreeBSD__
|
|
u_platform = 0;
|
|
k_platform = ELF_PLATFORM;
|
|
if (k_platform) {
|
|
@@ -783,22 +941,28 @@ static abi_ulong create_elf_tables(abi_ulong p, int argc, int envc,
|
|
/* FIXME - check return value of memcpy_to_target() for failure */
|
|
memcpy_to_target(sp, k_platform, len);
|
|
}
|
|
+#endif /* ! __FreeBSD__ */
|
|
/*
|
|
* Force 16 byte _final_ alignment here for generality.
|
|
*/
|
|
sp = sp &~ (abi_ulong)15;
|
|
+#ifdef __FreeBSD__
|
|
+ size = 0;
|
|
+#else
|
|
size = (DLINFO_ITEMS + 1) * 2;
|
|
if (k_platform)
|
|
size += 2;
|
|
#ifdef DLINFO_ARCH_ITEMS
|
|
size += DLINFO_ARCH_ITEMS * 2;
|
|
#endif
|
|
+#endif /* ! __FreeBSD__ */
|
|
size += envc + argc + 2;
|
|
size += (!ibcs ? 3 : 1); /* argc itself */
|
|
size *= n;
|
|
if (size & 15)
|
|
sp -= 16 - (size & 15);
|
|
|
|
+#ifndef __FreeBSD__
|
|
/* This is correct because Linux defines
|
|
* elf_addr_t as Elf32_Off / Elf64_Off
|
|
*/
|
|
@@ -833,6 +997,7 @@ static abi_ulong create_elf_tables(abi_ulong p, int argc, int envc,
|
|
ARCH_DLINFO;
|
|
#endif
|
|
#undef NEW_AUX_ENT
|
|
+#endif /* ! __FreeBSD__ */
|
|
|
|
sp = loader_build_argptr(envc, argc, sp, p, !ibcs);
|
|
return sp;
|
|
@@ -856,9 +1021,7 @@ static abi_ulong load_elf_interp(struct elfhdr * interp_elf_ex,
|
|
last_bss = 0;
|
|
error = 0;
|
|
|
|
-#ifdef BSWAP_NEEDED
|
|
bswap_ehdr(interp_elf_ex);
|
|
-#endif
|
|
/* First of all, some simple consistency checks */
|
|
if ((interp_elf_ex->e_type != ET_EXEC &&
|
|
interp_elf_ex->e_type != ET_DYN) ||
|
|
@@ -899,12 +1062,7 @@ static abi_ulong load_elf_interp(struct elfhdr * interp_elf_ex,
|
|
free (elf_phdata);
|
|
return retval;
|
|
}
|
|
-#ifdef BSWAP_NEEDED
|
|
- eppnt = elf_phdata;
|
|
- for (i=0; i<interp_elf_ex->e_phnum; i++, eppnt++) {
|
|
- bswap_phdr(eppnt);
|
|
- }
|
|
-#endif
|
|
+ bswap_phdr(elf_phdata, interp_elf_ex->e_phnum);
|
|
|
|
if (interp_elf_ex->e_type == ET_DYN) {
|
|
/* in order to avoid hardcoding the interpreter load
|
|
@@ -1049,9 +1207,7 @@ static void load_symbols(struct elfhdr *hdr, int fd)
|
|
for (i = 0; i < hdr->e_shnum; i++) {
|
|
if (read(fd, &sechdr, sizeof(sechdr)) != sizeof(sechdr))
|
|
return;
|
|
-#ifdef BSWAP_NEEDED
|
|
- bswap_shdr(&sechdr);
|
|
-#endif
|
|
+ bswap_shdr(&sechdr, 1);
|
|
if (sechdr.sh_type == SHT_SYMTAB) {
|
|
symtab = sechdr;
|
|
lseek(fd, hdr->e_shoff
|
|
@@ -1059,9 +1215,7 @@ static void load_symbols(struct elfhdr *hdr, int fd)
|
|
if (read(fd, &strtab, sizeof(strtab))
|
|
!= sizeof(strtab))
|
|
return;
|
|
-#ifdef BSWAP_NEEDED
|
|
- bswap_shdr(&strtab);
|
|
-#endif
|
|
+ bswap_shdr(&strtab, 1);
|
|
goto found;
|
|
}
|
|
}
|
|
@@ -1094,9 +1248,7 @@ static void load_symbols(struct elfhdr *hdr, int fd)
|
|
|
|
i = 0;
|
|
while (i < nsyms) {
|
|
-#ifdef BSWAP_NEEDED
|
|
bswap_sym(syms + i);
|
|
-#endif
|
|
// Throw away entries which we do not need.
|
|
if (syms[i].st_shndx == SHN_UNDEF ||
|
|
syms[i].st_shndx >= SHN_LORESERVE ||
|
|
@@ -1148,7 +1300,7 @@ static void load_symbols(struct elfhdr *hdr, int fd)
|
|
syminfos = s;
|
|
}
|
|
|
|
-int load_elf_binary(struct linux_binprm * bprm, struct target_pt_regs * regs,
|
|
+int load_elf_binary(struct bsd_binprm * bprm, struct target_pt_regs * regs,
|
|
struct image_info * info)
|
|
{
|
|
struct elfhdr elf_ex;
|
|
@@ -1178,9 +1330,7 @@ int load_elf_binary(struct linux_binprm * bprm, struct target_pt_regs * regs,
|
|
load_addr = 0;
|
|
load_bias = 0;
|
|
elf_ex = *((struct elfhdr *) bprm->buf); /* exec-header */
|
|
-#ifdef BSWAP_NEEDED
|
|
bswap_ehdr(&elf_ex);
|
|
-#endif
|
|
|
|
/* First of all, some simple consistency checks */
|
|
if ((elf_ex.e_type != ET_EXEC && elf_ex.e_type != ET_DYN) ||
|
|
@@ -1188,12 +1338,14 @@ int load_elf_binary(struct linux_binprm * bprm, struct target_pt_regs * regs,
|
|
return -ENOEXEC;
|
|
}
|
|
|
|
+#ifndef __FreeBSD__
|
|
bprm->p = copy_elf_strings(1, &bprm->filename, bprm->page, bprm->p);
|
|
bprm->p = copy_elf_strings(bprm->envc,bprm->envp,bprm->page,bprm->p);
|
|
bprm->p = copy_elf_strings(bprm->argc,bprm->argv,bprm->page,bprm->p);
|
|
if (!bprm->p) {
|
|
retval = -E2BIG;
|
|
}
|
|
+#endif /* ! __FreeBSD__ */
|
|
|
|
/* Now read in all of the header information */
|
|
elf_phdata = (struct elf_phdr *)malloc(elf_ex.e_phentsize*elf_ex.e_phnum);
|
|
@@ -1214,12 +1366,7 @@ int load_elf_binary(struct linux_binprm * bprm, struct target_pt_regs * regs,
|
|
return -errno;
|
|
}
|
|
|
|
-#ifdef BSWAP_NEEDED
|
|
- elf_ppnt = elf_phdata;
|
|
- for (i=0; i<elf_ex.e_phnum; i++, elf_ppnt++) {
|
|
- bswap_phdr(elf_ppnt);
|
|
- }
|
|
-#endif
|
|
+ bswap_phdr(elf_phdata, elf_ex.e_phnum);
|
|
elf_ppnt = elf_phdata;
|
|
|
|
elf_bss = 0;
|
|
@@ -1229,9 +1376,9 @@ int load_elf_binary(struct linux_binprm * bprm, struct target_pt_regs * regs,
|
|
elf_stack = ~((abi_ulong)0UL);
|
|
elf_interpreter = NULL;
|
|
start_code = ~((abi_ulong)0UL);
|
|
- end_code = 0;
|
|
- start_data = 0;
|
|
- end_data = 0;
|
|
+ end_code = (abi_ulong)0UL;
|
|
+ start_data = (abi_ulong)0UL;
|
|
+ end_data = (abi_ulong)0UL;
|
|
interp_ex.a_info = 0;
|
|
|
|
for(i=0;i < elf_ex.e_phnum; i++) {
|
|
@@ -1431,7 +1578,7 @@ int load_elf_binary(struct linux_binprm * bprm, struct target_pt_regs * regs,
|
|
perror("mmap");
|
|
exit(-1);
|
|
}
|
|
- load_bias = TARGET_ELF_PAGESTART(error - elf_ppnt->p_vaddr);
|
|
+ load_bias = TARGET_ELF_PAGESTART(error - elf_ppnt->p_vaddr);
|
|
}
|
|
|
|
error = target_mmap(TARGET_ELF_PAGESTART(load_bias + elf_ppnt->p_vaddr),
|
|
@@ -1541,12 +1688,13 @@ int load_elf_binary(struct linux_binprm * bprm, struct target_pt_regs * regs,
|
|
padzero(elf_bss, elf_brk);
|
|
|
|
#if 0
|
|
- printf("(start_brk) %x\n" , info->start_brk);
|
|
- printf("(end_code) %x\n" , info->end_code);
|
|
- printf("(start_code) %x\n" , info->start_code);
|
|
- printf("(end_data) %x\n" , info->end_data);
|
|
- printf("(start_stack) %x\n" , info->start_stack);
|
|
- printf("(brk) %x\n" , info->brk);
|
|
+ printf("(start_brk) 0x" TARGET_FMT_lx "\n" , info->start_brk);
|
|
+ printf("(end_code) 0x" TARGET_FMT_lx "\n" , info->end_code);
|
|
+ printf("(start_code) 0x" TARGET_FMT_lx "\n" , info->start_code);
|
|
+ printf("(start_data) 0x" TARGET_FMT_lx "\n" , info->start_data);
|
|
+ printf("(end_data) 0x" TARGET_FMT_lx "\n" , info->end_data);
|
|
+ printf("(start_stack) 0x" TARGET_FMT_lx "\n" , info->start_stack);
|
|
+ printf("(brk) 0x" TARGET_FMT_lx "\n" , info->brk);
|
|
#endif
|
|
|
|
if ( info->personality == PER_SVR4 )
|
|
@@ -1561,6 +1709,11 @@ int load_elf_binary(struct linux_binprm * bprm, struct target_pt_regs * regs,
|
|
|
|
info->entry = elf_entry;
|
|
|
|
+#ifdef USE_ELF_CORE_DUMP
|
|
+ /* bprm->core_dump = &elf_core_dump; */
|
|
+ bprm->core_dump = NULL;
|
|
+#endif
|
|
+
|
|
return 0;
|
|
}
|
|
|
|
diff --git a/bsd-user/freebsd/syscall_nr.h b/bsd-user/freebsd/syscall_nr.h
|
|
index 36336ab..e46571f 100644
|
|
--- a/bsd-user/freebsd/syscall_nr.h
|
|
+++ b/bsd-user/freebsd/syscall_nr.h
|
|
@@ -1,373 +1,448 @@
|
|
/*
|
|
* System call numbers.
|
|
*
|
|
- * $FreeBSD: src/sys/sys/syscall.h,v 1.224 2008/08/24 21:23:08 rwatson Exp $
|
|
- * created from FreeBSD: head/sys/kern/syscalls.master 182123 2008-08-24 21:20:35Z rwatson
|
|
+ * created from FreeBSD: releng/9.1/sys/kern/syscalls.master 229723 2012-01-06 19:29:16Z jhb
|
|
*/
|
|
|
|
-#define TARGET_FREEBSD_NR_syscall 0
|
|
-#define TARGET_FREEBSD_NR_exit 1
|
|
-#define TARGET_FREEBSD_NR_fork 2
|
|
-#define TARGET_FREEBSD_NR_read 3
|
|
-#define TARGET_FREEBSD_NR_write 4
|
|
-#define TARGET_FREEBSD_NR_open 5
|
|
-#define TARGET_FREEBSD_NR_close 6
|
|
-#define TARGET_FREEBSD_NR_wait4 7
|
|
-#define TARGET_FREEBSD_NR_link 9
|
|
-#define TARGET_FREEBSD_NR_unlink 10
|
|
-#define TARGET_FREEBSD_NR_chdir 12
|
|
-#define TARGET_FREEBSD_NR_fchdir 13
|
|
-#define TARGET_FREEBSD_NR_mknod 14
|
|
-#define TARGET_FREEBSD_NR_chmod 15
|
|
-#define TARGET_FREEBSD_NR_chown 16
|
|
-#define TARGET_FREEBSD_NR_break 17
|
|
-#define TARGET_FREEBSD_NR_freebsd4_getfsstat 18
|
|
-#define TARGET_FREEBSD_NR_getpid 20
|
|
-#define TARGET_FREEBSD_NR_mount 21
|
|
-#define TARGET_FREEBSD_NR_unmount 22
|
|
-#define TARGET_FREEBSD_NR_setuid 23
|
|
-#define TARGET_FREEBSD_NR_getuid 24
|
|
-#define TARGET_FREEBSD_NR_geteuid 25
|
|
-#define TARGET_FREEBSD_NR_ptrace 26
|
|
-#define TARGET_FREEBSD_NR_recvmsg 27
|
|
-#define TARGET_FREEBSD_NR_sendmsg 28
|
|
-#define TARGET_FREEBSD_NR_recvfrom 29
|
|
-#define TARGET_FREEBSD_NR_accept 30
|
|
-#define TARGET_FREEBSD_NR_getpeername 31
|
|
-#define TARGET_FREEBSD_NR_getsockname 32
|
|
-#define TARGET_FREEBSD_NR_access 33
|
|
-#define TARGET_FREEBSD_NR_chflags 34
|
|
-#define TARGET_FREEBSD_NR_fchflags 35
|
|
-#define TARGET_FREEBSD_NR_sync 36
|
|
-#define TARGET_FREEBSD_NR_kill 37
|
|
-#define TARGET_FREEBSD_NR_getppid 39
|
|
-#define TARGET_FREEBSD_NR_dup 41
|
|
-#define TARGET_FREEBSD_NR_pipe 42
|
|
-#define TARGET_FREEBSD_NR_getegid 43
|
|
-#define TARGET_FREEBSD_NR_profil 44
|
|
-#define TARGET_FREEBSD_NR_ktrace 45
|
|
-#define TARGET_FREEBSD_NR_getgid 47
|
|
-#define TARGET_FREEBSD_NR_getlogin 49
|
|
-#define TARGET_FREEBSD_NR_setlogin 50
|
|
-#define TARGET_FREEBSD_NR_acct 51
|
|
-#define TARGET_FREEBSD_NR_sigaltstack 53
|
|
-#define TARGET_FREEBSD_NR_ioctl 54
|
|
-#define TARGET_FREEBSD_NR_reboot 55
|
|
-#define TARGET_FREEBSD_NR_revoke 56
|
|
-#define TARGET_FREEBSD_NR_symlink 57
|
|
-#define TARGET_FREEBSD_NR_readlink 58
|
|
-#define TARGET_FREEBSD_NR_execve 59
|
|
-#define TARGET_FREEBSD_NR_umask 60
|
|
-#define TARGET_FREEBSD_NR_chroot 61
|
|
-#define TARGET_FREEBSD_NR_msync 65
|
|
-#define TARGET_FREEBSD_NR_vfork 66
|
|
-#define TARGET_FREEBSD_NR_sbrk 69
|
|
-#define TARGET_FREEBSD_NR_sstk 70
|
|
-#define TARGET_FREEBSD_NR_vadvise 72
|
|
-#define TARGET_FREEBSD_NR_munmap 73
|
|
-#define TARGET_FREEBSD_NR_mprotect 74
|
|
-#define TARGET_FREEBSD_NR_madvise 75
|
|
-#define TARGET_FREEBSD_NR_mincore 78
|
|
-#define TARGET_FREEBSD_NR_getgroups 79
|
|
-#define TARGET_FREEBSD_NR_setgroups 80
|
|
-#define TARGET_FREEBSD_NR_getpgrp 81
|
|
-#define TARGET_FREEBSD_NR_setpgid 82
|
|
-#define TARGET_FREEBSD_NR_setitimer 83
|
|
-#define TARGET_FREEBSD_NR_swapon 85
|
|
-#define TARGET_FREEBSD_NR_getitimer 86
|
|
-#define TARGET_FREEBSD_NR_getdtablesize 89
|
|
-#define TARGET_FREEBSD_NR_dup2 90
|
|
-#define TARGET_FREEBSD_NR_fcntl 92
|
|
-#define TARGET_FREEBSD_NR_select 93
|
|
-#define TARGET_FREEBSD_NR_fsync 95
|
|
-#define TARGET_FREEBSD_NR_setpriority 96
|
|
-#define TARGET_FREEBSD_NR_socket 97
|
|
-#define TARGET_FREEBSD_NR_connect 98
|
|
-#define TARGET_FREEBSD_NR_getpriority 100
|
|
-#define TARGET_FREEBSD_NR_bind 104
|
|
-#define TARGET_FREEBSD_NR_setsockopt 105
|
|
-#define TARGET_FREEBSD_NR_listen 106
|
|
-#define TARGET_FREEBSD_NR_gettimeofday 116
|
|
-#define TARGET_FREEBSD_NR_getrusage 117
|
|
-#define TARGET_FREEBSD_NR_getsockopt 118
|
|
-#define TARGET_FREEBSD_NR_readv 120
|
|
-#define TARGET_FREEBSD_NR_writev 121
|
|
-#define TARGET_FREEBSD_NR_settimeofday 122
|
|
-#define TARGET_FREEBSD_NR_fchown 123
|
|
-#define TARGET_FREEBSD_NR_fchmod 124
|
|
-#define TARGET_FREEBSD_NR_setreuid 126
|
|
-#define TARGET_FREEBSD_NR_setregid 127
|
|
-#define TARGET_FREEBSD_NR_rename 128
|
|
-#define TARGET_FREEBSD_NR_flock 131
|
|
-#define TARGET_FREEBSD_NR_mkfifo 132
|
|
-#define TARGET_FREEBSD_NR_sendto 133
|
|
-#define TARGET_FREEBSD_NR_shutdown 134
|
|
-#define TARGET_FREEBSD_NR_socketpair 135
|
|
-#define TARGET_FREEBSD_NR_mkdir 136
|
|
-#define TARGET_FREEBSD_NR_rmdir 137
|
|
-#define TARGET_FREEBSD_NR_utimes 138
|
|
-#define TARGET_FREEBSD_NR_adjtime 140
|
|
-#define TARGET_FREEBSD_NR_setsid 147
|
|
-#define TARGET_FREEBSD_NR_quotactl 148
|
|
-#define TARGET_FREEBSD_NR_nlm_syscall 154
|
|
-#define TARGET_FREEBSD_NR_nfssvc 155
|
|
-#define TARGET_FREEBSD_NR_freebsd4_statfs 157
|
|
-#define TARGET_FREEBSD_NR_freebsd4_fstatfs 158
|
|
-#define TARGET_FREEBSD_NR_lgetfh 160
|
|
-#define TARGET_FREEBSD_NR_getfh 161
|
|
-#define TARGET_FREEBSD_NR_getdomainname 162
|
|
-#define TARGET_FREEBSD_NR_setdomainname 163
|
|
-#define TARGET_FREEBSD_NR_uname 164
|
|
-#define TARGET_FREEBSD_NR_sysarch 165
|
|
-#define TARGET_FREEBSD_NR_rtprio 166
|
|
-#define TARGET_FREEBSD_NR_semsys 169
|
|
-#define TARGET_FREEBSD_NR_msgsys 170
|
|
-#define TARGET_FREEBSD_NR_shmsys 171
|
|
-#define TARGET_FREEBSD_NR_freebsd6_pread 173
|
|
-#define TARGET_FREEBSD_NR_freebsd6_pwrite 174
|
|
-#define TARGET_FREEBSD_NR_setfib 175
|
|
-#define TARGET_FREEBSD_NR_ntp_adjtime 176
|
|
-#define TARGET_FREEBSD_NR_setgid 181
|
|
-#define TARGET_FREEBSD_NR_setegid 182
|
|
-#define TARGET_FREEBSD_NR_seteuid 183
|
|
-#define TARGET_FREEBSD_NR_stat 188
|
|
-#define TARGET_FREEBSD_NR_fstat 189
|
|
-#define TARGET_FREEBSD_NR_lstat 190
|
|
-#define TARGET_FREEBSD_NR_pathconf 191
|
|
-#define TARGET_FREEBSD_NR_fpathconf 192
|
|
-#define TARGET_FREEBSD_NR_getrlimit 194
|
|
-#define TARGET_FREEBSD_NR_setrlimit 195
|
|
-#define TARGET_FREEBSD_NR_getdirentries 196
|
|
-#define TARGET_FREEBSD_NR_freebsd6_mmap 197
|
|
-#define TARGET_FREEBSD_NR___syscall 198
|
|
-#define TARGET_FREEBSD_NR_freebsd6_lseek 199
|
|
-#define TARGET_FREEBSD_NR_freebsd6_truncate 200
|
|
-#define TARGET_FREEBSD_NR_freebsd6_ftruncate 201
|
|
-#define TARGET_FREEBSD_NR___sysctl 202
|
|
-#define TARGET_FREEBSD_NR_mlock 203
|
|
-#define TARGET_FREEBSD_NR_munlock 204
|
|
-#define TARGET_FREEBSD_NR_undelete 205
|
|
-#define TARGET_FREEBSD_NR_futimes 206
|
|
-#define TARGET_FREEBSD_NR_getpgid 207
|
|
-#define TARGET_FREEBSD_NR_poll 209
|
|
-#define TARGET_FREEBSD_NR___semctl 220
|
|
-#define TARGET_FREEBSD_NR_semget 221
|
|
-#define TARGET_FREEBSD_NR_semop 222
|
|
-#define TARGET_FREEBSD_NR_msgctl 224
|
|
-#define TARGET_FREEBSD_NR_msgget 225
|
|
-#define TARGET_FREEBSD_NR_msgsnd 226
|
|
-#define TARGET_FREEBSD_NR_msgrcv 227
|
|
-#define TARGET_FREEBSD_NR_shmat 228
|
|
-#define TARGET_FREEBSD_NR_shmctl 229
|
|
-#define TARGET_FREEBSD_NR_shmdt 230
|
|
-#define TARGET_FREEBSD_NR_shmget 231
|
|
-#define TARGET_FREEBSD_NR_clock_gettime 232
|
|
-#define TARGET_FREEBSD_NR_clock_settime 233
|
|
-#define TARGET_FREEBSD_NR_clock_getres 234
|
|
-#define TARGET_FREEBSD_NR_ktimer_create 235
|
|
-#define TARGET_FREEBSD_NR_ktimer_delete 236
|
|
-#define TARGET_FREEBSD_NR_ktimer_settime 237
|
|
-#define TARGET_FREEBSD_NR_ktimer_gettime 238
|
|
-#define TARGET_FREEBSD_NR_ktimer_getoverrun 239
|
|
-#define TARGET_FREEBSD_NR_nanosleep 240
|
|
-#define TARGET_FREEBSD_NR_ntp_gettime 248
|
|
-#define TARGET_FREEBSD_NR_minherit 250
|
|
-#define TARGET_FREEBSD_NR_rfork 251
|
|
-#define TARGET_FREEBSD_NR_openbsd_poll 252
|
|
-#define TARGET_FREEBSD_NR_issetugid 253
|
|
-#define TARGET_FREEBSD_NR_lchown 254
|
|
-#define TARGET_FREEBSD_NR_aio_read 255
|
|
-#define TARGET_FREEBSD_NR_aio_write 256
|
|
-#define TARGET_FREEBSD_NR_lio_listio 257
|
|
-#define TARGET_FREEBSD_NR_getdents 272
|
|
-#define TARGET_FREEBSD_NR_lchmod 274
|
|
-#define TARGET_FREEBSD_NR_netbsd_lchown 275
|
|
-#define TARGET_FREEBSD_NR_lutimes 276
|
|
-#define TARGET_FREEBSD_NR_netbsd_msync 277
|
|
-#define TARGET_FREEBSD_NR_nstat 278
|
|
-#define TARGET_FREEBSD_NR_nfstat 279
|
|
-#define TARGET_FREEBSD_NR_nlstat 280
|
|
-#define TARGET_FREEBSD_NR_preadv 289
|
|
-#define TARGET_FREEBSD_NR_pwritev 290
|
|
-#define TARGET_FREEBSD_NR_freebsd4_fhstatfs 297
|
|
-#define TARGET_FREEBSD_NR_fhopen 298
|
|
-#define TARGET_FREEBSD_NR_fhstat 299
|
|
-#define TARGET_FREEBSD_NR_modnext 300
|
|
-#define TARGET_FREEBSD_NR_modstat 301
|
|
-#define TARGET_FREEBSD_NR_modfnext 302
|
|
-#define TARGET_FREEBSD_NR_modfind 303
|
|
-#define TARGET_FREEBSD_NR_kldload 304
|
|
-#define TARGET_FREEBSD_NR_kldunload 305
|
|
-#define TARGET_FREEBSD_NR_kldfind 306
|
|
-#define TARGET_FREEBSD_NR_kldnext 307
|
|
-#define TARGET_FREEBSD_NR_kldstat 308
|
|
-#define TARGET_FREEBSD_NR_kldfirstmod 309
|
|
-#define TARGET_FREEBSD_NR_getsid 310
|
|
-#define TARGET_FREEBSD_NR_setresuid 311
|
|
-#define TARGET_FREEBSD_NR_setresgid 312
|
|
-#define TARGET_FREEBSD_NR_aio_return 314
|
|
-#define TARGET_FREEBSD_NR_aio_suspend 315
|
|
-#define TARGET_FREEBSD_NR_aio_cancel 316
|
|
-#define TARGET_FREEBSD_NR_aio_error 317
|
|
-#define TARGET_FREEBSD_NR_oaio_read 318
|
|
-#define TARGET_FREEBSD_NR_oaio_write 319
|
|
-#define TARGET_FREEBSD_NR_olio_listio 320
|
|
-#define TARGET_FREEBSD_NR_yield 321
|
|
-#define TARGET_FREEBSD_NR_mlockall 324
|
|
-#define TARGET_FREEBSD_NR_munlockall 325
|
|
-#define TARGET_FREEBSD_NR___getcwd 326
|
|
-#define TARGET_FREEBSD_NR_sched_setparam 327
|
|
-#define TARGET_FREEBSD_NR_sched_getparam 328
|
|
-#define TARGET_FREEBSD_NR_sched_setscheduler 329
|
|
-#define TARGET_FREEBSD_NR_sched_getscheduler 330
|
|
-#define TARGET_FREEBSD_NR_sched_yield 331
|
|
-#define TARGET_FREEBSD_NR_sched_get_priority_max 332
|
|
-#define TARGET_FREEBSD_NR_sched_get_priority_min 333
|
|
-#define TARGET_FREEBSD_NR_sched_rr_get_interval 334
|
|
-#define TARGET_FREEBSD_NR_utrace 335
|
|
-#define TARGET_FREEBSD_NR_freebsd4_sendfile 336
|
|
-#define TARGET_FREEBSD_NR_kldsym 337
|
|
-#define TARGET_FREEBSD_NR_jail 338
|
|
-#define TARGET_FREEBSD_NR_sigprocmask 340
|
|
-#define TARGET_FREEBSD_NR_sigsuspend 341
|
|
-#define TARGET_FREEBSD_NR_freebsd4_sigaction 342
|
|
-#define TARGET_FREEBSD_NR_sigpending 343
|
|
-#define TARGET_FREEBSD_NR_freebsd4_sigreturn 344
|
|
-#define TARGET_FREEBSD_NR_sigtimedwait 345
|
|
-#define TARGET_FREEBSD_NR_sigwaitinfo 346
|
|
-#define TARGET_FREEBSD_NR___acl_get_file 347
|
|
-#define TARGET_FREEBSD_NR___acl_set_file 348
|
|
-#define TARGET_FREEBSD_NR___acl_get_fd 349
|
|
-#define TARGET_FREEBSD_NR___acl_set_fd 350
|
|
-#define TARGET_FREEBSD_NR___acl_delete_file 351
|
|
-#define TARGET_FREEBSD_NR___acl_delete_fd 352
|
|
-#define TARGET_FREEBSD_NR___acl_aclcheck_file 353
|
|
-#define TARGET_FREEBSD_NR___acl_aclcheck_fd 354
|
|
-#define TARGET_FREEBSD_NR_extattrctl 355
|
|
-#define TARGET_FREEBSD_NR_extattr_set_file 356
|
|
-#define TARGET_FREEBSD_NR_extattr_get_file 357
|
|
-#define TARGET_FREEBSD_NR_extattr_delete_file 358
|
|
-#define TARGET_FREEBSD_NR_aio_waitcomplete 359
|
|
-#define TARGET_FREEBSD_NR_getresuid 360
|
|
-#define TARGET_FREEBSD_NR_getresgid 361
|
|
-#define TARGET_FREEBSD_NR_kqueue 362
|
|
-#define TARGET_FREEBSD_NR_kevent 363
|
|
-#define TARGET_FREEBSD_NR_extattr_set_fd 371
|
|
-#define TARGET_FREEBSD_NR_extattr_get_fd 372
|
|
-#define TARGET_FREEBSD_NR_extattr_delete_fd 373
|
|
-#define TARGET_FREEBSD_NR___setugid 374
|
|
-#define TARGET_FREEBSD_NR_nfsclnt 375
|
|
-#define TARGET_FREEBSD_NR_eaccess 376
|
|
-#define TARGET_FREEBSD_NR_nmount 378
|
|
-#define TARGET_FREEBSD_NR___mac_get_proc 384
|
|
-#define TARGET_FREEBSD_NR___mac_set_proc 385
|
|
-#define TARGET_FREEBSD_NR___mac_get_fd 386
|
|
-#define TARGET_FREEBSD_NR___mac_get_file 387
|
|
-#define TARGET_FREEBSD_NR___mac_set_fd 388
|
|
-#define TARGET_FREEBSD_NR___mac_set_file 389
|
|
-#define TARGET_FREEBSD_NR_kenv 390
|
|
-#define TARGET_FREEBSD_NR_lchflags 391
|
|
-#define TARGET_FREEBSD_NR_uuidgen 392
|
|
-#define TARGET_FREEBSD_NR_sendfile 393
|
|
-#define TARGET_FREEBSD_NR_mac_syscall 394
|
|
-#define TARGET_FREEBSD_NR_getfsstat 395
|
|
-#define TARGET_FREEBSD_NR_statfs 396
|
|
-#define TARGET_FREEBSD_NR_fstatfs 397
|
|
-#define TARGET_FREEBSD_NR_fhstatfs 398
|
|
-#define TARGET_FREEBSD_NR_ksem_close 400
|
|
-#define TARGET_FREEBSD_NR_ksem_post 401
|
|
-#define TARGET_FREEBSD_NR_ksem_wait 402
|
|
-#define TARGET_FREEBSD_NR_ksem_trywait 403
|
|
-#define TARGET_FREEBSD_NR_ksem_init 404
|
|
-#define TARGET_FREEBSD_NR_ksem_open 405
|
|
-#define TARGET_FREEBSD_NR_ksem_unlink 406
|
|
-#define TARGET_FREEBSD_NR_ksem_getvalue 407
|
|
-#define TARGET_FREEBSD_NR_ksem_destroy 408
|
|
-#define TARGET_FREEBSD_NR___mac_get_pid 409
|
|
-#define TARGET_FREEBSD_NR___mac_get_link 410
|
|
-#define TARGET_FREEBSD_NR___mac_set_link 411
|
|
-#define TARGET_FREEBSD_NR_extattr_set_link 412
|
|
-#define TARGET_FREEBSD_NR_extattr_get_link 413
|
|
-#define TARGET_FREEBSD_NR_extattr_delete_link 414
|
|
-#define TARGET_FREEBSD_NR___mac_execve 415
|
|
-#define TARGET_FREEBSD_NR_sigaction 416
|
|
-#define TARGET_FREEBSD_NR_sigreturn 417
|
|
-#define TARGET_FREEBSD_NR_getcontext 421
|
|
-#define TARGET_FREEBSD_NR_setcontext 422
|
|
-#define TARGET_FREEBSD_NR_swapcontext 423
|
|
-#define TARGET_FREEBSD_NR_swapoff 424
|
|
-#define TARGET_FREEBSD_NR___acl_get_link 425
|
|
-#define TARGET_FREEBSD_NR___acl_set_link 426
|
|
-#define TARGET_FREEBSD_NR___acl_delete_link 427
|
|
-#define TARGET_FREEBSD_NR___acl_aclcheck_link 428
|
|
-#define TARGET_FREEBSD_NR_sigwait 429
|
|
-#define TARGET_FREEBSD_NR_thr_create 430
|
|
-#define TARGET_FREEBSD_NR_thr_exit 431
|
|
-#define TARGET_FREEBSD_NR_thr_self 432
|
|
-#define TARGET_FREEBSD_NR_thr_kill 433
|
|
-#define TARGET_FREEBSD_NR__umtx_lock 434
|
|
-#define TARGET_FREEBSD_NR__umtx_unlock 435
|
|
-#define TARGET_FREEBSD_NR_jail_attach 436
|
|
-#define TARGET_FREEBSD_NR_extattr_list_fd 437
|
|
-#define TARGET_FREEBSD_NR_extattr_list_file 438
|
|
-#define TARGET_FREEBSD_NR_extattr_list_link 439
|
|
-#define TARGET_FREEBSD_NR_ksem_timedwait 441
|
|
-#define TARGET_FREEBSD_NR_thr_suspend 442
|
|
-#define TARGET_FREEBSD_NR_thr_wake 443
|
|
-#define TARGET_FREEBSD_NR_kldunloadf 444
|
|
-#define TARGET_FREEBSD_NR_audit 445
|
|
-#define TARGET_FREEBSD_NR_auditon 446
|
|
-#define TARGET_FREEBSD_NR_getauid 447
|
|
-#define TARGET_FREEBSD_NR_setauid 448
|
|
-#define TARGET_FREEBSD_NR_getaudit 449
|
|
-#define TARGET_FREEBSD_NR_setaudit 450
|
|
-#define TARGET_FREEBSD_NR_getaudit_addr 451
|
|
-#define TARGET_FREEBSD_NR_setaudit_addr 452
|
|
-#define TARGET_FREEBSD_NR_auditctl 453
|
|
-#define TARGET_FREEBSD_NR__umtx_op 454
|
|
-#define TARGET_FREEBSD_NR_thr_new 455
|
|
-#define TARGET_FREEBSD_NR_sigqueue 456
|
|
-#define TARGET_FREEBSD_NR_kmq_open 457
|
|
-#define TARGET_FREEBSD_NR_kmq_setattr 458
|
|
-#define TARGET_FREEBSD_NR_kmq_timedreceive 459
|
|
-#define TARGET_FREEBSD_NR_kmq_timedsend 460
|
|
-#define TARGET_FREEBSD_NR_kmq_notify 461
|
|
-#define TARGET_FREEBSD_NR_kmq_unlink 462
|
|
-#define TARGET_FREEBSD_NR_abort2 463
|
|
-#define TARGET_FREEBSD_NR_thr_set_name 464
|
|
-#define TARGET_FREEBSD_NR_aio_fsync 465
|
|
-#define TARGET_FREEBSD_NR_rtprio_thread 466
|
|
-#define TARGET_FREEBSD_NR_sctp_peeloff 471
|
|
-#define TARGET_FREEBSD_NR_sctp_generic_sendmsg 472
|
|
-#define TARGET_FREEBSD_NR_sctp_generic_sendmsg_iov 473
|
|
-#define TARGET_FREEBSD_NR_sctp_generic_recvmsg 474
|
|
-#define TARGET_FREEBSD_NR_pread 475
|
|
-#define TARGET_FREEBSD_NR_pwrite 476
|
|
-#define TARGET_FREEBSD_NR_mmap 477
|
|
-#define TARGET_FREEBSD_NR_lseek 478
|
|
-#define TARGET_FREEBSD_NR_truncate 479
|
|
-#define TARGET_FREEBSD_NR_ftruncate 480
|
|
-#define TARGET_FREEBSD_NR_thr_kill2 481
|
|
-#define TARGET_FREEBSD_NR_shm_open 482
|
|
-#define TARGET_FREEBSD_NR_shm_unlink 483
|
|
-#define TARGET_FREEBSD_NR_cpuset 484
|
|
-#define TARGET_FREEBSD_NR_cpuset_setid 485
|
|
-#define TARGET_FREEBSD_NR_cpuset_getid 486
|
|
-#define TARGET_FREEBSD_NR_cpuset_getaffinity 487
|
|
-#define TARGET_FREEBSD_NR_cpuset_setaffinity 488
|
|
-#define TARGET_FREEBSD_NR_faccessat 489
|
|
-#define TARGET_FREEBSD_NR_fchmodat 490
|
|
-#define TARGET_FREEBSD_NR_fchownat 491
|
|
-#define TARGET_FREEBSD_NR_fexecve 492
|
|
-#define TARGET_FREEBSD_NR_fstatat 493
|
|
-#define TARGET_FREEBSD_NR_futimesat 494
|
|
-#define TARGET_FREEBSD_NR_linkat 495
|
|
-#define TARGET_FREEBSD_NR_mkdirat 496
|
|
-#define TARGET_FREEBSD_NR_mkfifoat 497
|
|
-#define TARGET_FREEBSD_NR_mknodat 498
|
|
-#define TARGET_FREEBSD_NR_openat 499
|
|
-#define TARGET_FREEBSD_NR_readlinkat 500
|
|
-#define TARGET_FREEBSD_NR_renameat 501
|
|
-#define TARGET_FREEBSD_NR_symlinkat 502
|
|
-#define TARGET_FREEBSD_NR_unlinkat 503
|
|
-#define TARGET_FREEBSD_NR_posix_openpt 504
|
|
+#define TARGET_FREEBSD_NR_syscall 0
|
|
+#define TARGET_FREEBSD_NR_exit 1
|
|
+#define TARGET_FREEBSD_NR_fork 2
|
|
+#define TARGET_FREEBSD_NR_read 3
|
|
+#define TARGET_FREEBSD_NR_write 4
|
|
+#define TARGET_FREEBSD_NR_open 5
|
|
+#define TARGET_FREEBSD_NR_close 6
|
|
+#define TARGET_FREEBSD_NR_wait4 7
|
|
+ /* 8 is old creat */
|
|
+#define TARGET_FREEBSD_NR_link 9
|
|
+#define TARGET_FREEBSD_NR_unlink 10
|
|
+ /* 11 is obsolete execv */
|
|
+#define TARGET_FREEBSD_NR_chdir 12
|
|
+#define TARGET_FREEBSD_NR_fchdir 13
|
|
+#define TARGET_FREEBSD_NR_mknod 14
|
|
+#define TARGET_FREEBSD_NR_chmod 15
|
|
+#define TARGET_FREEBSD_NR_chown 16
|
|
+#define TARGET_FREEBSD_NR_break 17
|
|
+#define TARGET_FREEBSD_NR_freebsd4_getfsstat 18
|
|
+ /* 19 is old lseek */
|
|
+#define TARGET_FREEBSD_NR_getpid 20
|
|
+#define TARGET_FREEBSD_NR_mount 21
|
|
+#define TARGET_FREEBSD_NR_unmount 22
|
|
+#define TARGET_FREEBSD_NR_setuid 23
|
|
+#define TARGET_FREEBSD_NR_getuid 24
|
|
+#define TARGET_FREEBSD_NR_geteuid 25
|
|
+#define TARGET_FREEBSD_NR_ptrace 26
|
|
+#define TARGET_FREEBSD_NR_recvmsg 27
|
|
+#define TARGET_FREEBSD_NR_sendmsg 28
|
|
+#define TARGET_FREEBSD_NR_recvfrom 29
|
|
+#define TARGET_FREEBSD_NR_accept 30
|
|
+#define TARGET_FREEBSD_NR_getpeername 31
|
|
+#define TARGET_FREEBSD_NR_getsockname 32
|
|
+#define TARGET_FREEBSD_NR_access 33
|
|
+#define TARGET_FREEBSD_NR_chflags 34
|
|
+#define TARGET_FREEBSD_NR_fchflags 35
|
|
+#define TARGET_FREEBSD_NR_sync 36
|
|
+#define TARGET_FREEBSD_NR_kill 37
|
|
+ /* 38 is old stat */
|
|
+#define TARGET_FREEBSD_NR_getppid 39
|
|
+ /* 40 is old lstat */
|
|
+#define TARGET_FREEBSD_NR_dup 41
|
|
+#define TARGET_FREEBSD_NR_pipe 42
|
|
+#define TARGET_FREEBSD_NR_getegid 43
|
|
+#define TARGET_FREEBSD_NR_profil 44
|
|
+#define TARGET_FREEBSD_NR_ktrace 45
|
|
+ /* 46 is old sigaction */
|
|
+#define TARGET_FREEBSD_NR_getgid 47
|
|
+ /* 48 is old sigprocmask */
|
|
+#define TARGET_FREEBSD_NR_getlogin 49
|
|
+#define TARGET_FREEBSD_NR_setlogin 50
|
|
+#define TARGET_FREEBSD_NR_acct 51
|
|
+ /* 52 is old sigpending */
|
|
+#define TARGET_FREEBSD_NR_sigaltstack 53
|
|
+#define TARGET_FREEBSD_NR_ioctl 54
|
|
+#define TARGET_FREEBSD_NR_reboot 55
|
|
+#define TARGET_FREEBSD_NR_revoke 56
|
|
+#define TARGET_FREEBSD_NR_symlink 57
|
|
+#define TARGET_FREEBSD_NR_readlink 58
|
|
+#define TARGET_FREEBSD_NR_execve 59
|
|
+#define TARGET_FREEBSD_NR_umask 60
|
|
+#define TARGET_FREEBSD_NR_chroot 61
|
|
+ /* 62 is old fstat */
|
|
+ /* 63 is old getkerninfo */
|
|
+ /* 64 is old getpagesize */
|
|
+#define TARGET_FREEBSD_NR_msync 65
|
|
+#define TARGET_FREEBSD_NR_vfork 66
|
|
+ /* 67 is obsolete vread */
|
|
+ /* 68 is obsolete vwrite */
|
|
+#define TARGET_FREEBSD_NR_sbrk 69
|
|
+#define TARGET_FREEBSD_NR_sstk 70
|
|
+ /* 71 is old mmap */
|
|
+#define TARGET_FREEBSD_NR_vadvise 72
|
|
+#define TARGET_FREEBSD_NR_munmap 73
|
|
+#define TARGET_FREEBSD_NR_mprotect 74
|
|
+#define TARGET_FREEBSD_NR_madvise 75
|
|
+ /* 76 is obsolete vhangup */
|
|
+ /* 77 is obsolete vlimit */
|
|
+#define TARGET_FREEBSD_NR_mincore 78
|
|
+#define TARGET_FREEBSD_NR_getgroups 79
|
|
+#define TARGET_FREEBSD_NR_setgroups 80
|
|
+#define TARGET_FREEBSD_NR_getpgrp 81
|
|
+#define TARGET_FREEBSD_NR_setpgid 82
|
|
+#define TARGET_FREEBSD_NR_setitimer 83
|
|
+ /* 84 is old wait */
|
|
+#define TARGET_FREEBSD_NR_swapon 85
|
|
+#define TARGET_FREEBSD_NR_getitimer 86
|
|
+ /* 87 is old gethostname */
|
|
+ /* 88 is old sethostname */
|
|
+#define TARGET_FREEBSD_NR_getdtablesize 89
|
|
+#define TARGET_FREEBSD_NR_dup2 90
|
|
+#define TARGET_FREEBSD_NR_fcntl 92
|
|
+#define TARGET_FREEBSD_NR_select 93
|
|
+#define TARGET_FREEBSD_NR_fsync 95
|
|
+#define TARGET_FREEBSD_NR_setpriority 96
|
|
+#define TARGET_FREEBSD_NR_socket 97
|
|
+#define TARGET_FREEBSD_NR_connect 98
|
|
+ /* 99 is old accept */
|
|
+#define TARGET_FREEBSD_NR_getpriority 100
|
|
+ /* 101 is old send */
|
|
+ /* 102 is old recv */
|
|
+ /* 103 is old sigreturn */
|
|
+#define TARGET_FREEBSD_NR_bind 104
|
|
+#define TARGET_FREEBSD_NR_setsockopt 105
|
|
+#define TARGET_FREEBSD_NR_listen 106
|
|
+ /* 107 is obsolete vtimes */
|
|
+ /* 108 is old sigvec */
|
|
+ /* 109 is old sigblock */
|
|
+ /* 110 is old sigsetmask */
|
|
+ /* 111 is old sigsuspend */
|
|
+ /* 112 is old sigstack */
|
|
+ /* 113 is old recvmsg */
|
|
+ /* 114 is old sendmsg */
|
|
+ /* 115 is obsolete vtrace */
|
|
+#define TARGET_FREEBSD_NR_gettimeofday 116
|
|
+#define TARGET_FREEBSD_NR_getrusage 117
|
|
+#define TARGET_FREEBSD_NR_getsockopt 118
|
|
+#define TARGET_FREEBSD_NR_readv 120
|
|
+#define TARGET_FREEBSD_NR_writev 121
|
|
+#define TARGET_FREEBSD_NR_settimeofday 122
|
|
+#define TARGET_FREEBSD_NR_fchown 123
|
|
+#define TARGET_FREEBSD_NR_fchmod 124
|
|
+ /* 125 is old recvfrom */
|
|
+#define TARGET_FREEBSD_NR_setreuid 126
|
|
+#define TARGET_FREEBSD_NR_setregid 127
|
|
+#define TARGET_FREEBSD_NR_rename 128
|
|
+ /* 129 is old truncate */
|
|
+ /* 130 is old ftruncate */
|
|
+#define TARGET_FREEBSD_NR_flock 131
|
|
+#define TARGET_FREEBSD_NR_mkfifo 132
|
|
+#define TARGET_FREEBSD_NR_sendto 133
|
|
+#define TARGET_FREEBSD_NR_shutdown 134
|
|
+#define TARGET_FREEBSD_NR_socketpair 135
|
|
+#define TARGET_FREEBSD_NR_mkdir 136
|
|
+#define TARGET_FREEBSD_NR_rmdir 137
|
|
+#define TARGET_FREEBSD_NR_utimes 138
|
|
+ /* 139 is obsolete 4.2 sigreturn */
|
|
+#define TARGET_FREEBSD_NR_adjtime 140
|
|
+ /* 141 is old getpeername */
|
|
+ /* 142 is old gethostid */
|
|
+ /* 143 is old sethostid */
|
|
+ /* 144 is old getrlimit */
|
|
+ /* 145 is old setrlimit */
|
|
+ /* 146 is old killpg */
|
|
+#define TARGET_FREEBSD_NR_setsid 147
|
|
+#define TARGET_FREEBSD_NR_quotactl 148
|
|
+ /* 149 is old quota */
|
|
+ /* 150 is old getsockname */
|
|
+#define TARGET_FREEBSD_NR_nlm_syscall 154
|
|
+#define TARGET_FREEBSD_NR_nfssvc 155
|
|
+ /* 156 is old getdirentries */
|
|
+#define TARGET_FREEBSD_NR_freebsd4_statfs 157
|
|
+#define TARGET_FREEBSD_NR_freebsd4_fstatfs 158
|
|
+#define TARGET_FREEBSD_NR_lgetfh 160
|
|
+#define TARGET_FREEBSD_NR_getfh 161
|
|
+#define TARGET_FREEBSD_NR_freebsd4_getdomainname 162
|
|
+#define TARGET_FREEBSD_NR_freebsd4_setdomainname 163
|
|
+#define TARGET_FREEBSD_NR_freebsd4_uname 164
|
|
+#define TARGET_FREEBSD_NR_sysarch 165
|
|
+#define TARGET_FREEBSD_NR_rtprio 166
|
|
+#define TARGET_FREEBSD_NR_semsys 169
|
|
+#define TARGET_FREEBSD_NR_msgsys 170
|
|
+#define TARGET_FREEBSD_NR_shmsys 171
|
|
+#define TARGET_FREEBSD_NR_freebsd6_pread 173
|
|
+#define TARGET_FREEBSD_NR_freebsd6_pwrite 174
|
|
+#define TARGET_FREEBSD_NR_setfib 175
|
|
+#define TARGET_FREEBSD_NR_ntp_adjtime 176
|
|
+#define TARGET_FREEBSD_NR_setgid 181
|
|
+#define TARGET_FREEBSD_NR_setegid 182
|
|
+#define TARGET_FREEBSD_NR_seteuid 183
|
|
+#define TARGET_FREEBSD_NR_stat 188
|
|
+#define TARGET_FREEBSD_NR_fstat 189
|
|
+#define TARGET_FREEBSD_NR_lstat 190
|
|
+#define TARGET_FREEBSD_NR_pathconf 191
|
|
+#define TARGET_FREEBSD_NR_fpathconf 192
|
|
+#define TARGET_FREEBSD_NR_getrlimit 194
|
|
+#define TARGET_FREEBSD_NR_setrlimit 195
|
|
+#define TARGET_FREEBSD_NR_getdirentries 196
|
|
+#define TARGET_FREEBSD_NR_freebsd6_mmap 197
|
|
+#define TARGET_FREEBSD_NR___syscall 198
|
|
+#define TARGET_FREEBSD_NR_freebsd6_lseek 199
|
|
+#define TARGET_FREEBSD_NR_freebsd6_truncate 200
|
|
+#define TARGET_FREEBSD_NR_freebsd6_ftruncate 201
|
|
+#define TARGET_FREEBSD_NR___sysctl 202
|
|
+#define TARGET_FREEBSD_NR_mlock 203
|
|
+#define TARGET_FREEBSD_NR_munlock 204
|
|
+#define TARGET_FREEBSD_NR_undelete 205
|
|
+#define TARGET_FREEBSD_NR_futimes 206
|
|
+#define TARGET_FREEBSD_NR_getpgid 207
|
|
+#define TARGET_FREEBSD_NR_poll 209
|
|
+#define TARGET_FREEBSD_NR_freebsd7___semctl 220
|
|
+#define TARGET_FREEBSD_NR_semget 221
|
|
+#define TARGET_FREEBSD_NR_semop 222
|
|
+#define TARGET_FREEBSD_NR_freebsd7_msgctl 224
|
|
+#define TARGET_FREEBSD_NR_msgget 225
|
|
+#define TARGET_FREEBSD_NR_msgsnd 226
|
|
+#define TARGET_FREEBSD_NR_msgrcv 227
|
|
+#define TARGET_FREEBSD_NR_shmat 228
|
|
+#define TARGET_FREEBSD_NR_freebsd7_shmctl 229
|
|
+#define TARGET_FREEBSD_NR_shmdt 230
|
|
+#define TARGET_FREEBSD_NR_shmget 231
|
|
+#define TARGET_FREEBSD_NR_clock_gettime 232
|
|
+#define TARGET_FREEBSD_NR_clock_settime 233
|
|
+#define TARGET_FREEBSD_NR_clock_getres 234
|
|
+#define TARGET_FREEBSD_NR_ktimer_create 235
|
|
+#define TARGET_FREEBSD_NR_ktimer_delete 236
|
|
+#define TARGET_FREEBSD_NR_ktimer_settime 237
|
|
+#define TARGET_FREEBSD_NR_ktimer_gettime 238
|
|
+#define TARGET_FREEBSD_NR_ktimer_getoverrun 239
|
|
+#define TARGET_FREEBSD_NR_nanosleep 240
|
|
+#define TARGET_FREEBSD_NR_ntp_gettime 248
|
|
+#define TARGET_FREEBSD_NR_minherit 250
|
|
+#define TARGET_FREEBSD_NR_rfork 251
|
|
+#define TARGET_FREEBSD_NR_openbsd_poll 252
|
|
+#define TARGET_FREEBSD_NR_issetugid 253
|
|
+#define TARGET_FREEBSD_NR_lchown 254
|
|
+#define TARGET_FREEBSD_NR_aio_read 255
|
|
+#define TARGET_FREEBSD_NR_aio_write 256
|
|
+#define TARGET_FREEBSD_NR_lio_listio 257
|
|
+#define TARGET_FREEBSD_NR_getdents 272
|
|
+#define TARGET_FREEBSD_NR_lchmod 274
|
|
+#define TARGET_FREEBSD_NR_netbsd_lchown 275
|
|
+#define TARGET_FREEBSD_NR_lutimes 276
|
|
+#define TARGET_FREEBSD_NR_netbsd_msync 277
|
|
+#define TARGET_FREEBSD_NR_nstat 278
|
|
+#define TARGET_FREEBSD_NR_nfstat 279
|
|
+#define TARGET_FREEBSD_NR_nlstat 280
|
|
+#define TARGET_FREEBSD_NR_preadv 289
|
|
+#define TARGET_FREEBSD_NR_pwritev 290
|
|
+#define TARGET_FREEBSD_NR_freebsd4_fhstatfs 297
|
|
+#define TARGET_FREEBSD_NR_fhopen 298
|
|
+#define TARGET_FREEBSD_NR_fhstat 299
|
|
+#define TARGET_FREEBSD_NR_modnext 300
|
|
+#define TARGET_FREEBSD_NR_modstat 301
|
|
+#define TARGET_FREEBSD_NR_modfnext 302
|
|
+#define TARGET_FREEBSD_NR_modfind 303
|
|
+#define TARGET_FREEBSD_NR_kldload 304
|
|
+#define TARGET_FREEBSD_NR_kldunload 305
|
|
+#define TARGET_FREEBSD_NR_kldfind 306
|
|
+#define TARGET_FREEBSD_NR_kldnext 307
|
|
+#define TARGET_FREEBSD_NR_kldstat 308
|
|
+#define TARGET_FREEBSD_NR_kldfirstmod 309
|
|
+#define TARGET_FREEBSD_NR_getsid 310
|
|
+#define TARGET_FREEBSD_NR_setresuid 311
|
|
+#define TARGET_FREEBSD_NR_setresgid 312
|
|
+ /* 313 is obsolete signanosleep */
|
|
+#define TARGET_FREEBSD_NR_aio_return 314
|
|
+#define TARGET_FREEBSD_NR_aio_suspend 315
|
|
+#define TARGET_FREEBSD_NR_aio_cancel 316
|
|
+#define TARGET_FREEBSD_NR_aio_error 317
|
|
+#define TARGET_FREEBSD_NR_oaio_read 318
|
|
+#define TARGET_FREEBSD_NR_oaio_write 319
|
|
+#define TARGET_FREEBSD_NR_olio_listio 320
|
|
+#define TARGET_FREEBSD_NR_yield 321
|
|
+ /* 322 is obsolete thr_sleep */
|
|
+ /* 323 is obsolete thr_wakeup */
|
|
+#define TARGET_FREEBSD_NR_mlockall 324
|
|
+#define TARGET_FREEBSD_NR_munlockall 325
|
|
+#define TARGET_FREEBSD_NR___getcwd 326
|
|
+#define TARGET_FREEBSD_NR_sched_setparam 327
|
|
+#define TARGET_FREEBSD_NR_sched_getparam 328
|
|
+#define TARGET_FREEBSD_NR_sched_setscheduler 329
|
|
+#define TARGET_FREEBSD_NR_sched_getscheduler 330
|
|
+#define TARGET_FREEBSD_NR_sched_yield 331
|
|
+#define TARGET_FREEBSD_NR_sched_get_priority_max 332
|
|
+#define TARGET_FREEBSD_NR_sched_get_priority_min 333
|
|
+#define TARGET_FREEBSD_NR_sched_rr_get_interval 334
|
|
+#define TARGET_FREEBSD_NR_utrace 335
|
|
+#define TARGET_FREEBSD_NR_freebsd4_sendfile 336
|
|
+#define TARGET_FREEBSD_NR_kldsym 337
|
|
+#define TARGET_FREEBSD_NR_jail 338
|
|
+#define TARGET_FREEBSD_NR_nnpfs_syscall 339
|
|
+#define TARGET_FREEBSD_NR_sigprocmask 340
|
|
+#define TARGET_FREEBSD_NR_sigsuspend 341
|
|
+#define TARGET_FREEBSD_NR_freebsd4_sigaction 342
|
|
+#define TARGET_FREEBSD_NR_sigpending 343
|
|
+#define TARGET_FREEBSD_NR_freebsd4_sigreturn 344
|
|
+#define TARGET_FREEBSD_NR_sigtimedwait 345
|
|
+#define TARGET_FREEBSD_NR_sigwaitinfo 346
|
|
+#define TARGET_FREEBSD_NR___acl_get_file 347
|
|
+#define TARGET_FREEBSD_NR___acl_set_file 348
|
|
+#define TARGET_FREEBSD_NR___acl_get_fd 349
|
|
+#define TARGET_FREEBSD_NR___acl_set_fd 350
|
|
+#define TARGET_FREEBSD_NR___acl_delete_file 351
|
|
+#define TARGET_FREEBSD_NR___acl_delete_fd 352
|
|
+#define TARGET_FREEBSD_NR___acl_aclcheck_file 353
|
|
+#define TARGET_FREEBSD_NR___acl_aclcheck_fd 354
|
|
+#define TARGET_FREEBSD_NR_extattrctl 355
|
|
+#define TARGET_FREEBSD_NR_extattr_set_file 356
|
|
+#define TARGET_FREEBSD_NR_extattr_get_file 357
|
|
+#define TARGET_FREEBSD_NR_extattr_delete_file 358
|
|
+#define TARGET_FREEBSD_NR_aio_waitcomplete 359
|
|
+#define TARGET_FREEBSD_NR_getresuid 360
|
|
+#define TARGET_FREEBSD_NR_getresgid 361
|
|
+#define TARGET_FREEBSD_NR_kqueue 362
|
|
+#define TARGET_FREEBSD_NR_kevent 363
|
|
+#define TARGET_FREEBSD_NR_extattr_set_fd 371
|
|
+#define TARGET_FREEBSD_NR_extattr_get_fd 372
|
|
+#define TARGET_FREEBSD_NR_extattr_delete_fd 373
|
|
+#define TARGET_FREEBSD_NR___setugid 374
|
|
+#define TARGET_FREEBSD_NR_eaccess 376
|
|
+#define TARGET_FREEBSD_NR_afs3_syscall 377
|
|
+#define TARGET_FREEBSD_NR_nmount 378
|
|
+#define TARGET_FREEBSD_NR___mac_get_proc 384
|
|
+#define TARGET_FREEBSD_NR___mac_set_proc 385
|
|
+#define TARGET_FREEBSD_NR___mac_get_fd 386
|
|
+#define TARGET_FREEBSD_NR___mac_get_file 387
|
|
+#define TARGET_FREEBSD_NR___mac_set_fd 388
|
|
+#define TARGET_FREEBSD_NR___mac_set_file 389
|
|
+#define TARGET_FREEBSD_NR_kenv 390
|
|
+#define TARGET_FREEBSD_NR_lchflags 391
|
|
+#define TARGET_FREEBSD_NR_uuidgen 392
|
|
+#define TARGET_FREEBSD_NR_sendfile 393
|
|
+#define TARGET_FREEBSD_NR_mac_syscall 394
|
|
+#define TARGET_FREEBSD_NR_getfsstat 395
|
|
+#define TARGET_FREEBSD_NR_statfs 396
|
|
+#define TARGET_FREEBSD_NR_fstatfs 397
|
|
+#define TARGET_FREEBSD_NR_fhstatfs 398
|
|
+#define TARGET_FREEBSD_NR_ksem_close 400
|
|
+#define TARGET_FREEBSD_NR_ksem_post 401
|
|
+#define TARGET_FREEBSD_NR_ksem_wait 402
|
|
+#define TARGET_FREEBSD_NR_ksem_trywait 403
|
|
+#define TARGET_FREEBSD_NR_ksem_init 404
|
|
+#define TARGET_FREEBSD_NR_ksem_open 405
|
|
+#define TARGET_FREEBSD_NR_ksem_unlink 406
|
|
+#define TARGET_FREEBSD_NR_ksem_getvalue 407
|
|
+#define TARGET_FREEBSD_NR_ksem_destroy 408
|
|
+#define TARGET_FREEBSD_NR___mac_get_pid 409
|
|
+#define TARGET_FREEBSD_NR___mac_get_link 410
|
|
+#define TARGET_FREEBSD_NR___mac_set_link 411
|
|
+#define TARGET_FREEBSD_NR_extattr_set_link 412
|
|
+#define TARGET_FREEBSD_NR_extattr_get_link 413
|
|
+#define TARGET_FREEBSD_NR_extattr_delete_link 414
|
|
+#define TARGET_FREEBSD_NR___mac_execve 415
|
|
+#define TARGET_FREEBSD_NR_sigaction 416
|
|
+#define TARGET_FREEBSD_NR_sigreturn 417
|
|
+#define TARGET_FREEBSD_NR_getcontext 421
|
|
+#define TARGET_FREEBSD_NR_setcontext 422
|
|
+#define TARGET_FREEBSD_NR_swapcontext 423
|
|
+#define TARGET_FREEBSD_NR_swapoff 424
|
|
+#define TARGET_FREEBSD_NR___acl_get_link 425
|
|
+#define TARGET_FREEBSD_NR___acl_set_link 426
|
|
+#define TARGET_FREEBSD_NR___acl_delete_link 427
|
|
+#define TARGET_FREEBSD_NR___acl_aclcheck_link 428
|
|
+#define TARGET_FREEBSD_NR_sigwait 429
|
|
+#define TARGET_FREEBSD_NR_thr_create 430
|
|
+#define TARGET_FREEBSD_NR_thr_exit 431
|
|
+#define TARGET_FREEBSD_NR_thr_self 432
|
|
+#define TARGET_FREEBSD_NR_thr_kill 433
|
|
+#define TARGET_FREEBSD_NR__umtx_lock 434
|
|
+#define TARGET_FREEBSD_NR__umtx_unlock 435
|
|
+#define TARGET_FREEBSD_NR_jail_attach 436
|
|
+#define TARGET_FREEBSD_NR_extattr_list_fd 437
|
|
+#define TARGET_FREEBSD_NR_extattr_list_file 438
|
|
+#define TARGET_FREEBSD_NR_extattr_list_link 439
|
|
+#define TARGET_FREEBSD_NR_ksem_timedwait 441
|
|
+#define TARGET_FREEBSD_NR_thr_suspend 442
|
|
+#define TARGET_FREEBSD_NR_thr_wake 443
|
|
+#define TARGET_FREEBSD_NR_kldunloadf 444
|
|
+#define TARGET_FREEBSD_NR_audit 445
|
|
+#define TARGET_FREEBSD_NR_auditon 446
|
|
+#define TARGET_FREEBSD_NR_getauid 447
|
|
+#define TARGET_FREEBSD_NR_setauid 448
|
|
+#define TARGET_FREEBSD_NR_getaudit 449
|
|
+#define TARGET_FREEBSD_NR_setaudit 450
|
|
+#define TARGET_FREEBSD_NR_getaudit_addr 451
|
|
+#define TARGET_FREEBSD_NR_setaudit_addr 452
|
|
+#define TARGET_FREEBSD_NR_auditctl 453
|
|
+#define TARGET_FREEBSD_NR__umtx_op 454
|
|
+#define TARGET_FREEBSD_NR_thr_new 455
|
|
+#define TARGET_FREEBSD_NR_sigqueue 456
|
|
+#define TARGET_FREEBSD_NR_kmq_open 457
|
|
+#define TARGET_FREEBSD_NR_kmq_setattr 458
|
|
+#define TARGET_FREEBSD_NR_kmq_timedreceive 459
|
|
+#define TARGET_FREEBSD_NR_kmq_timedsend 460
|
|
+#define TARGET_FREEBSD_NR_kmq_notify 461
|
|
+#define TARGET_FREEBSD_NR_kmq_unlink 462
|
|
+#define TARGET_FREEBSD_NR_abort2 463
|
|
+#define TARGET_FREEBSD_NR_thr_set_name 464
|
|
+#define TARGET_FREEBSD_NR_aio_fsync 465
|
|
+#define TARGET_FREEBSD_NR_rtprio_thread 466
|
|
+#define TARGET_FREEBSD_NR_sctp_peeloff 471
|
|
+#define TARGET_FREEBSD_NR_sctp_generic_sendmsg 472
|
|
+#define TARGET_FREEBSD_NR_sctp_generic_sendmsg_iov 473
|
|
+#define TARGET_FREEBSD_NR_sctp_generic_recvmsg 474
|
|
+#define TARGET_FREEBSD_NR_pread 475
|
|
+#define TARGET_FREEBSD_NR_pwrite 476
|
|
+#define TARGET_FREEBSD_NR_mmap 477
|
|
+#define TARGET_FREEBSD_NR_lseek 478
|
|
+#define TARGET_FREEBSD_NR_truncate 479
|
|
+#define TARGET_FREEBSD_NR_ftruncate 480
|
|
+#define TARGET_FREEBSD_NR_thr_kill2 481
|
|
+#define TARGET_FREEBSD_NR_shm_open 482
|
|
+#define TARGET_FREEBSD_NR_shm_unlink 483
|
|
+#define TARGET_FREEBSD_NR_cpuset 484
|
|
+#define TARGET_FREEBSD_NR_cpuset_setid 485
|
|
+#define TARGET_FREEBSD_NR_cpuset_getid 486
|
|
+#define TARGET_FREEBSD_NR_cpuset_getaffinity 487
|
|
+#define TARGET_FREEBSD_NR_cpuset_setaffinity 488
|
|
+#define TARGET_FREEBSD_NR_faccessat 489
|
|
+#define TARGET_FREEBSD_NR_fchmodat 490
|
|
+#define TARGET_FREEBSD_NR_fchownat 491
|
|
+#define TARGET_FREEBSD_NR_fexecve 492
|
|
+#define TARGET_FREEBSD_NR_fstatat 493
|
|
+#define TARGET_FREEBSD_NR_futimesat 494
|
|
+#define TARGET_FREEBSD_NR_linkat 495
|
|
+#define TARGET_FREEBSD_NR_mkdirat 496
|
|
+#define TARGET_FREEBSD_NR_mkfifoat 497
|
|
+#define TARGET_FREEBSD_NR_mknodat 498
|
|
+#define TARGET_FREEBSD_NR_openat 499
|
|
+#define TARGET_FREEBSD_NR_readlinkat 500
|
|
+#define TARGET_FREEBSD_NR_renameat 501
|
|
+#define TARGET_FREEBSD_NR_symlinkat 502
|
|
+#define TARGET_FREEBSD_NR_unlinkat 503
|
|
+#define TARGET_FREEBSD_NR_posix_openpt 504
|
|
+#define TARGET_FREEBSD_NR_gssd_syscall 505
|
|
+#define TARGET_FREEBSD_NR_jail_get 506
|
|
+#define TARGET_FREEBSD_NR_jail_set 507
|
|
+#define TARGET_FREEBSD_NR_jail_remove 508
|
|
+#define TARGET_FREEBSD_NR_closefrom 509
|
|
+#define TARGET_FREEBSD_NR___semctl 510
|
|
+#define TARGET_FREEBSD_NR_msgctl 511
|
|
+#define TARGET_FREEBSD_NR_shmctl 512
|
|
+#define TARGET_FREEBSD_NR_lpathconf 513
|
|
+#define TARGET_FREEBSD_NR_cap_new 514
|
|
+#define TARGET_FREEBSD_NR_cap_getrights 515
|
|
+#define TARGET_FREEBSD_NR_cap_enter 516
|
|
+#define TARGET_FREEBSD_NR_cap_getmode 517
|
|
+#define TARGET_FREEBSD_NR_pdfork 518
|
|
+#define TARGET_FREEBSD_NR_pdkill 519
|
|
+#define TARGET_FREEBSD_NR_pdgetpid 520
|
|
+#define TARGET_FREEBSD_NR_pselect 522
|
|
+#define TARGET_FREEBSD_NR_getloginclass 523
|
|
+#define TARGET_FREEBSD_NR_setloginclass 524
|
|
+#define TARGET_FREEBSD_NR_rctl_get_racct 525
|
|
+#define TARGET_FREEBSD_NR_rctl_get_rules 526
|
|
+#define TARGET_FREEBSD_NR_rctl_get_limits 527
|
|
+#define TARGET_FREEBSD_NR_rctl_add_rule 528
|
|
+#define TARGET_FREEBSD_NR_rctl_remove_rule 529
|
|
+#define TARGET_FREEBSD_NR_posix_fallocate 530
|
|
+#define TARGET_FREEBSD_NR_posix_fadvise 531
|
|
+#define TARGET_FREEBSD_NR_MAXSYSCALL 532
|
|
diff --git a/bsd-user/i386/target_signal.h b/bsd-user/i386/target_signal.h
|
|
index 2ef36d1..285e7f9 100644
|
|
--- a/bsd-user/i386/target_signal.h
|
|
+++ b/bsd-user/i386/target_signal.h
|
|
@@ -3,18 +3,12 @@
|
|
|
|
#include "cpu.h"
|
|
|
|
-/* this struct defines a stack used during syscall handling */
|
|
-
|
|
-typedef struct target_sigaltstack {
|
|
- abi_ulong ss_sp;
|
|
- abi_long ss_flags;
|
|
- abi_ulong ss_size;
|
|
-} target_stack_t;
|
|
-
|
|
-
|
|
static inline abi_ulong get_sp_from_cpustate(CPUX86State *state)
|
|
{
|
|
return state->regs[R_ESP];
|
|
}
|
|
|
|
+#define TARGET_MINSIGSTKSZ (512 * 4)
|
|
+#define TARGET_SIGSTKSZ (TARGET_MINSIGSTKSZ + 32768)
|
|
+
|
|
#endif /* TARGET_SIGNAL_H */
|
|
diff --git a/bsd-user/i386/target_vmparam.h b/bsd-user/i386/target_vmparam.h
|
|
new file mode 100644
|
|
index 0000000..8fc98d5
|
|
--- /dev/null
|
|
+++ b/bsd-user/i386/target_vmparam.h
|
|
@@ -0,0 +1,27 @@
|
|
+#ifndef _TARGET_VMPARAM_H_
|
|
+#define _TARGET_VMPARAM_H_
|
|
+
|
|
+#if defined(__FreeBSD__)
|
|
+
|
|
+#define TARGET_USRSTACK (0xbfc00000)
|
|
+
|
|
+struct target_ps_strings {
|
|
+ abi_ulong ps_argvstr;
|
|
+ uint32_t ps_nargvstr;
|
|
+ abi_ulong ps_envstr;
|
|
+ uint32_t ps_nenvstr;
|
|
+};
|
|
+
|
|
+#define TARGET_SPACE_USRSPACE 4096
|
|
+#define TARGET_ARG_MAX 262144
|
|
+
|
|
+#define TARGET_PS_STRINGS (TARGET_USRSTACK - sizeof(struct target_ps_strings))
|
|
+
|
|
+#define TARGET_SZSIGCODE 0
|
|
+
|
|
+#else
|
|
+
|
|
+#define TARGET_USRSTACK 0
|
|
+#endif
|
|
+
|
|
+#endif /* _TARGET_VMPARAM_H_ */
|
|
diff --git a/bsd-user/main.c b/bsd-user/main.c
|
|
index b4e42f3..146f022 100644
|
|
--- a/bsd-user/main.c
|
|
+++ b/bsd-user/main.c
|
|
@@ -642,6 +642,243 @@ void cpu_loop(CPUARMState *env)
|
|
|
|
#endif
|
|
|
|
+#if defined(TARGET_MIPS) || defined(TARGET_MIPS64)
|
|
+
|
|
+/*
|
|
+ * From sys/mips/mips/trap.c syscalls have the following stored away in the
|
|
+ * registers:
|
|
+ *
|
|
+ * v0(2): if either SYS___syscall (198) or SYS_syscall (0) then indirect syscall
|
|
+ * otherwise it is a direct syscall.
|
|
+ *
|
|
+ * If direct syscall:
|
|
+ *
|
|
+ * MIPS MIPS64
|
|
+ * v0(2): v0(2) syscall #
|
|
+ * a0(4): a0(4) arg0
|
|
+ * a1(5): a1(5) arg1
|
|
+ * a2(6): a2(6) arg2
|
|
+ * a3(7): a3(7) arg3
|
|
+ * t4(12): a4(8) arg4
|
|
+ * t5(13): a5(9) arg5
|
|
+ * t6(14): a6(10) arg6
|
|
+ * t7(15): a7(11) arg7
|
|
+ *
|
|
+ * If indirect syscall:
|
|
+ *
|
|
+ * MIPS MIPS64
|
|
+ * a0(4): a0(4) syscall #
|
|
+ * a1(5): a1(5) arg0
|
|
+ * a2(6): a2(6) arg1
|
|
+ * a3(7): a3(7) arg2
|
|
+ * t4(12): a4(8) arg3
|
|
+ * t5(13): a5(9) arg4
|
|
+ * t6(14): a6(10) arg5
|
|
+ * t7(15): a7(11) arg6
|
|
+ *
|
|
+ */
|
|
+
|
|
+#include <sys/syscall.h> /* For SYS_[__]syscall, SYS_MAXSYSCALL */
|
|
+
|
|
+static int do_store_exclusive(CPUMIPSState *env)
|
|
+{
|
|
+ target_ulong addr;
|
|
+ target_ulong page_addr;
|
|
+ target_ulong val;
|
|
+ int flags;
|
|
+ int segv = 0;
|
|
+ int reg;
|
|
+ int d;
|
|
+
|
|
+ addr = env->lladdr;
|
|
+ page_addr = addr & TARGET_PAGE_MASK;
|
|
+ start_exclusive();
|
|
+ mmap_lock();
|
|
+ flags = page_get_flags(page_addr);
|
|
+ if ((flags & PAGE_READ) == 0) {
|
|
+ segv = 1;
|
|
+ } else {
|
|
+ reg = env->llreg & 0x1f;
|
|
+ d = (env->llreg & 0x20) != 0;
|
|
+ if (d) {
|
|
+ segv = get_user_s64(val, addr);
|
|
+ } else {
|
|
+ segv = get_user_s32(val, addr);
|
|
+ }
|
|
+ if (!segv) {
|
|
+ if (val != env->llval) {
|
|
+ env->active_tc.gpr[reg] = 0;
|
|
+ } else {
|
|
+ if (d) {
|
|
+ segv =
|
|
+ put_user_u64(env->llnewval, addr);
|
|
+ } else {
|
|
+ segv =
|
|
+ put_user_u32(env->llnewval, addr);
|
|
+ }
|
|
+ if (!segv) {
|
|
+ env->active_tc.gpr[reg] = 1;
|
|
+ }
|
|
+ }
|
|
+ }
|
|
+ }
|
|
+ env->lladdr = -1;
|
|
+ if (!segv) {
|
|
+ env->active_tc.PC += 4;
|
|
+ }
|
|
+ mmap_unlock();
|
|
+ end_exclusive();
|
|
+ return (segv);
|
|
+}
|
|
+
|
|
+void cpu_loop(CPUMIPSState *env)
|
|
+{
|
|
+ target_siginfo_t info;
|
|
+ int trapnr;
|
|
+ abi_long ret;
|
|
+ unsigned int syscall_num;
|
|
+
|
|
+ for(;;) {
|
|
+ cpu_exec_start(env);
|
|
+ trapnr = cpu_mips_exec(env);
|
|
+ cpu_exec_end(env);
|
|
+ switch(trapnr) {
|
|
+ case EXCP_SYSCALL: /* syscall exception */
|
|
+ syscall_num = env->active_tc.gpr[2]; /* v0 */
|
|
+ env->active_tc.PC += 4;
|
|
+ if (syscall_num >= SYS_MAXSYSCALL) {
|
|
+ ret = -TARGET_ENOSYS;
|
|
+ } else {
|
|
+ if (SYS_syscall == syscall_num ||
|
|
+ SYS___syscall == syscall_num) {
|
|
+#if defined(TARGET_MIPS64)
|
|
+ ret = do_freebsd_syscall(env,
|
|
+ env->active_tc.gpr[4],/* syscall #*/
|
|
+ env->active_tc.gpr[5], /* arg0 */
|
|
+ env->active_tc.gpr[6], /* arg1 */
|
|
+ env->active_tc.gpr[7], /* arg2 */
|
|
+ env->active_tc.gpr[8], /* arg3 */
|
|
+ env->active_tc.gpr[9], /* arg4 */
|
|
+ env->active_tc.gpr[10],/* arg5 */
|
|
+ env->active_tc.gpr[11],/* arg6 */
|
|
+ 0 /* no arg 7 */);
|
|
+ } else {
|
|
+ ret = do_freebsd_syscall(env,
|
|
+ syscall_num,
|
|
+ env->active_tc.gpr[4],
|
|
+ env->active_tc.gpr[5],
|
|
+ env->active_tc.gpr[6],
|
|
+ env->active_tc.gpr[7],
|
|
+ env->active_tc.gpr[8],
|
|
+ env->active_tc.gpr[9],
|
|
+ env->active_tc.gpr[10],
|
|
+ env->active_tc.gpr[11]
|
|
+ );
|
|
+
|
|
+#else /* ! TARGET_MIPS64 */
|
|
+ /* indirect syscall */
|
|
+ ret = do_freebsd_syscall(env,
|
|
+ env->active_tc.gpr[4],/* syscall #*/
|
|
+ env->active_tc.gpr[5], /* a1/arg0 */
|
|
+ env->active_tc.gpr[6], /* a2/arg1 */
|
|
+ env->active_tc.gpr[7], /* a3/arg2 */
|
|
+ env->active_tc.gpr[12],/* t4/arg3 */
|
|
+ env->active_tc.gpr[13],/* t5/arg4 */
|
|
+ env->active_tc.gpr[14],/* t6/arg5 */
|
|
+ env->active_tc.gpr[15],/* t7/arg6 */
|
|
+ 0 /* no arg7 */ );
|
|
+ } else {
|
|
+ /* direct syscall */
|
|
+ ret = do_freebsd_syscall(env,
|
|
+ syscall_num,
|
|
+ env->active_tc.gpr[4], /* a0/arg0 */
|
|
+ env->active_tc.gpr[5], /* a1/arg1 */
|
|
+ env->active_tc.gpr[6], /* a2/arg2 */
|
|
+ env->active_tc.gpr[7], /* a3/arg3 */
|
|
+ env->active_tc.gpr[12],/* t4/arg4 */
|
|
+ env->active_tc.gpr[13],/* t5/arg5 */
|
|
+ env->active_tc.gpr[14],/* t6/arg6 */
|
|
+ env->active_tc.gpr[15] /* t7/arg7 */
|
|
+ );
|
|
+#endif /* ! TARGET_MIPS64 */
|
|
+ }
|
|
+ }
|
|
+/* done_syscall: */
|
|
+ if (-TARGET_QEMU_ESIGRETURN == ret) {
|
|
+ /*
|
|
+ * Returning from a successful sigreturn
|
|
+ * syscall. Avoid clobbering register state.
|
|
+ */
|
|
+ break;
|
|
+ }
|
|
+ if ((unsigned int)ret >= (unsigned int)(-1133)) {
|
|
+ env->active_tc.gpr[7] = 1;
|
|
+ ret = -ret;
|
|
+ } else {
|
|
+ env->active_tc.gpr[7] = 0;
|
|
+ }
|
|
+ env->active_tc.gpr[2] = ret; /* v0 <- ret */
|
|
+ break;
|
|
+
|
|
+ case EXCP_TLBL: /* TLB miss on load */
|
|
+ case EXCP_TLBS: /* TLB miss on store */
|
|
+ case EXCP_AdEL: /* bad address on load */
|
|
+ case EXCP_AdES: /* bad address on store */
|
|
+ info.si_signo = TARGET_SIGSEGV;
|
|
+ info.si_errno = 0;
|
|
+ /* XXX: check env->error_code */
|
|
+ info.si_code = TARGET_SEGV_MAPERR;
|
|
+ info.si_addr = env->CP0_BadVAddr;
|
|
+ queue_signal(env, info.si_signo, &info);
|
|
+ break;
|
|
+
|
|
+ case EXCP_CpU: /* coprocessor unusable */
|
|
+ case EXCP_RI: /* reserved instruction */
|
|
+ info.si_signo = TARGET_SIGILL;
|
|
+ info.si_errno = 0;
|
|
+ info.si_code = 0;
|
|
+ queue_signal(env, info.si_signo, &info);
|
|
+ break;
|
|
+
|
|
+ case EXCP_INTERRUPT: /* async interrupt */
|
|
+ /* just indicate that signals should be handled asap */
|
|
+ break;
|
|
+
|
|
+ case EXCP_DEBUG: /* cpu stopped after a breakpoint */
|
|
+ {
|
|
+ int sig;
|
|
+
|
|
+ sig = gdb_handlesig(env, TARGET_SIGTRAP);
|
|
+ if (sig) {
|
|
+ info.si_signo = sig;
|
|
+ info.si_errno = 0;
|
|
+ info.si_code = TARGET_TRAP_BRKPT;
|
|
+ queue_signal(env, info.si_signo, &info);
|
|
+ }
|
|
+ }
|
|
+ break;
|
|
+
|
|
+ case EXCP_SC:
|
|
+ if (do_store_exclusive(env)) {
|
|
+ info.si_signo = TARGET_SIGSEGV;
|
|
+ info.si_errno = 0;
|
|
+ info.si_code = TARGET_SEGV_MAPERR;
|
|
+ info.si_addr = env->active_tc.PC;
|
|
+ queue_signal(env, info.si_signo, &info);
|
|
+ }
|
|
+ break;
|
|
+
|
|
+ default:
|
|
+ fprintf(stderr, "qemu: unhandled CPU exception "
|
|
+ "0x%x - aborting\n", trapnr);
|
|
+ cpu_dump_state(env, stderr, fprintf, 0);
|
|
+ abort();
|
|
+ }
|
|
+ process_pending_signals(env);
|
|
+ }
|
|
+}
|
|
+#endif /* defined(TARGET_MIPS) */
|
|
+
|
|
#ifdef TARGET_SPARC
|
|
#define SPARC64_STACK_BIAS 2047
|
|
|
|
@@ -969,6 +1206,15 @@ static void usage(void)
|
|
|
|
THREAD CPUArchState *thread_env;
|
|
|
|
+void stop_all_tasks(void)
|
|
+{
|
|
+ /*
|
|
+ * We trust when using NPTL (pthreads) start_exclusive() handles thread
|
|
+ * stopping correctly.
|
|
+ */
|
|
+ start_exclusive();
|
|
+}
|
|
+
|
|
/* Assumes contents are already zeroed. */
|
|
void init_task_state(TaskState *ts)
|
|
{
|
|
@@ -990,6 +1236,7 @@ int main(int argc, char **argv)
|
|
const char *log_mask = NULL;
|
|
struct target_pt_regs regs1, *regs = ®s1;
|
|
struct image_info info1, *info = &info1;
|
|
+ struct bsd_binprm bprm;
|
|
TaskState ts1, *ts = &ts1;
|
|
CPUArchState *env;
|
|
int optind;
|
|
@@ -997,7 +1244,11 @@ int main(int argc, char **argv)
|
|
int gdbstub_port = 0;
|
|
char **target_environ, **wrk;
|
|
envlist_t *envlist = NULL;
|
|
+#ifdef __FreeBSD__
|
|
+ bsd_type = target_freebsd;
|
|
+#else
|
|
bsd_type = target_openbsd;
|
|
+#endif
|
|
|
|
if (argc <= 1)
|
|
usage();
|
|
@@ -1141,6 +1392,8 @@ int main(int argc, char **argv)
|
|
/* Zero out image_info */
|
|
memset(info, 0, sizeof(struct image_info));
|
|
|
|
+ memset(&bprm, 0, sizeof(bprm));
|
|
+
|
|
/* Scan interp_prefix dir for replacement files. */
|
|
init_paths(interp_prefix);
|
|
|
|
@@ -1151,6 +1404,12 @@ int main(int argc, char **argv)
|
|
#else
|
|
cpu_model = "qemu32";
|
|
#endif
|
|
+#elif defined(TARGET_MIPS) || defined(TARGET_MIPS64)
|
|
+#if defined(TARGET_ABI_MIPSN32) || defined(TARGET_ABI_MIPSN64)
|
|
+ cpu_model = "20Kc";
|
|
+#else
|
|
+ cpu_model = "24Kf";
|
|
+#endif
|
|
#elif defined(TARGET_SPARC)
|
|
#ifdef TARGET_SPARC64
|
|
cpu_model = "TI UltraSparc II";
|
|
@@ -1211,7 +1470,8 @@ int main(int argc, char **argv)
|
|
}
|
|
#endif /* CONFIG_USE_GUEST_BASE */
|
|
|
|
- if (loader_exec(filename, argv+optind, target_environ, regs, info) != 0) {
|
|
+ if (loader_exec(filename, argv+optind, target_environ, regs, info,
|
|
+ &bprm)!= 0) {
|
|
printf("Error loading %s\n", filename);
|
|
_exit(1);
|
|
}
|
|
@@ -1256,6 +1516,7 @@ int main(int argc, char **argv)
|
|
memset(ts, 0, sizeof(TaskState));
|
|
init_task_state(ts);
|
|
ts->info = info;
|
|
+ ts->bprm = &bprm;
|
|
env->opaque = ts;
|
|
|
|
#if defined(TARGET_I386)
|
|
@@ -1394,6 +1655,20 @@ int main(int argc, char **argv)
|
|
env->regs[i] = regs->uregs[i];
|
|
}
|
|
}
|
|
+#elif defined(TARGET_MIPS)
|
|
+ {
|
|
+ int i;
|
|
+ for(i = 0; i < 32; i++) {
|
|
+ env->active_tc.gpr[i] = regs->regs[i];
|
|
+ }
|
|
+ env->active_tc.PC = regs->cp0_epc & ~(target_ulong)1;
|
|
+ if (regs->cp0_epc & 1) {
|
|
+ env->hflags |= MIPS_HFLAG_M16;
|
|
+ }
|
|
+#if defined(TARGET_MIPS64)
|
|
+ env->hflags |= MIPS_HFLAG_UX;
|
|
+#endif
|
|
+ }
|
|
#else
|
|
#error unsupported target CPU
|
|
#endif
|
|
diff --git a/bsd-user/mips/syscall.h b/bsd-user/mips/syscall.h
|
|
new file mode 100644
|
|
index 0000000..8923556
|
|
--- /dev/null
|
|
+++ b/bsd-user/mips/syscall.h
|
|
@@ -0,0 +1,21 @@
|
|
+
|
|
+/* this struct defines the way the registers are stored on the
|
|
+ stack during a system call. */
|
|
+
|
|
+struct target_pt_regs {
|
|
+ /* Pad bytes for argument save space on the stack. */
|
|
+ abi_ulong pad0[6];
|
|
+
|
|
+ /* Saved main processor registers. */
|
|
+ abi_ulong regs[32];
|
|
+
|
|
+ /* Saved special registers. */
|
|
+ abi_ulong cp0_status;
|
|
+ abi_ulong lo;
|
|
+ abi_ulong hi;
|
|
+ abi_ulong cp0_badvaddr;
|
|
+ abi_ulong cp0_cause;
|
|
+ abi_ulong cp0_epc;
|
|
+};
|
|
+
|
|
+#define UNAME_MACHINE "mips"
|
|
diff --git a/bsd-user/mips/target_signal.h b/bsd-user/mips/target_signal.h
|
|
new file mode 100644
|
|
index 0000000..28871c3
|
|
--- /dev/null
|
|
+++ b/bsd-user/mips/target_signal.h
|
|
@@ -0,0 +1,14 @@
|
|
+#ifndef TARGET_SIGNAL_H
|
|
+#define TARGET_SIGNAL_H
|
|
+
|
|
+#include "cpu.h"
|
|
+
|
|
+#define TARGET_MINSIGSTKSZ (512 * 4)
|
|
+#define TARGET_SIGSTKSZ (TARGET_MINSIGSTKSZ + 32768)
|
|
+
|
|
+static inline abi_ulong get_sp_from_cpustate(CPUMIPSState *state)
|
|
+{
|
|
+ return state->active_tc.gpr[29];
|
|
+}
|
|
+
|
|
+#endif /* TARGET_SIGNAL_H */
|
|
diff --git a/bsd-user/mips/target_vmparam.h b/bsd-user/mips/target_vmparam.h
|
|
new file mode 100644
|
|
index 0000000..9fca7f3
|
|
--- /dev/null
|
|
+++ b/bsd-user/mips/target_vmparam.h
|
|
@@ -0,0 +1,30 @@
|
|
+#ifndef _TARGET_VMPARAM_H_
|
|
+#define _TARGET_VMPARAM_H_
|
|
+
|
|
+#if defined(__FreeBSD__)
|
|
+#define TARGET_VM_MINUSER_ADDRESS (0x00000000)
|
|
+#define TARGET_VM_MAXUSER_ADDRESS (0x80000000)
|
|
+
|
|
+#define TARGET_USRSTACK (TARGET_VM_MAXUSER_ADDRESS - TARGET_PAGE_SIZE)
|
|
+
|
|
+struct target_ps_strings {
|
|
+ abi_ulong ps_argvstr;
|
|
+ uint32_t ps_nargvstr;
|
|
+ abi_ulong ps_envstr;
|
|
+ uint32_t ps_nenvstr;
|
|
+};
|
|
+
|
|
+#define TARGET_SPACE_USRSPACE 4096
|
|
+#define TARGET_ARG_MAX 262144
|
|
+
|
|
+#define TARGET_PS_STRINGS (TARGET_USRSTACK - sizeof(struct target_ps_strings))
|
|
+
|
|
+#define TARGET_SZSIGCODE 0
|
|
+
|
|
+#else
|
|
+
|
|
+#define TARGET_USRSTACK 0
|
|
+#endif
|
|
+
|
|
+
|
|
+#endif /* _TARGET_VMPARAM_H_ */
|
|
diff --git a/bsd-user/mips64/syscall.h b/bsd-user/mips64/syscall.h
|
|
new file mode 100644
|
|
index 0000000..fca3634
|
|
--- /dev/null
|
|
+++ b/bsd-user/mips64/syscall.h
|
|
@@ -0,0 +1,21 @@
|
|
+
|
|
+/* this struct defines the way the registers are stored on the
|
|
+ stack during a system call. */
|
|
+
|
|
+struct target_pt_regs {
|
|
+ /* Saved main processor registers. */
|
|
+ abi_ulong regs[32];
|
|
+
|
|
+ /* Saved special registers. */
|
|
+ abi_ulong cp0_status;
|
|
+ abi_ulong lo;
|
|
+ abi_ulong hi;
|
|
+ abi_ulong cp0_badvaddr;
|
|
+ abi_ulong cp0_cause;
|
|
+ abi_ulong cp0_epc;
|
|
+};
|
|
+
|
|
+/* Nasty hack: define a fake errno value for use by sigreturn. */
|
|
+#define TARGET_QEMU_ESIGRETURN 255
|
|
+
|
|
+#define UNAME_MACHINE "mips64"
|
|
diff --git a/bsd-user/mips64/target_signal.h b/bsd-user/mips64/target_signal.h
|
|
new file mode 100644
|
|
index 0000000..d671f4e
|
|
--- /dev/null
|
|
+++ b/bsd-user/mips64/target_signal.h
|
|
@@ -0,0 +1,17 @@
|
|
+#ifndef TARGET_SIGNAL_H
|
|
+#define TARGET_SIGNAL_H
|
|
+
|
|
+#include "cpu.h"
|
|
+
|
|
+#define TARGET_MINSIGSTKSZ (512 * 4)
|
|
+#define TARGET_SIGSTKSZ (TARGET_MINSIGSTKSZ + 32768)
|
|
+#define TARGET_SZSIGCODE 16
|
|
+
|
|
+#define TARGET_UCONTEXT_MAGIC 0xACEDBADE
|
|
+
|
|
+static inline abi_ulong get_sp_from_cpustate(CPUMIPSState *state)
|
|
+{
|
|
+ return state->active_tc.gpr[29];
|
|
+}
|
|
+
|
|
+#endif /* TARGET_SIGNAL_H */
|
|
diff --git a/bsd-user/mips64/target_vmparam.h b/bsd-user/mips64/target_vmparam.h
|
|
new file mode 100644
|
|
index 0000000..47c2267
|
|
--- /dev/null
|
|
+++ b/bsd-user/mips64/target_vmparam.h
|
|
@@ -0,0 +1,28 @@
|
|
+#ifndef _TARGET_VMPARAM_H_
|
|
+#define _TARGET_VMPARAM_H_
|
|
+
|
|
+#if defined(__FreeBSD__)
|
|
+
|
|
+#define TARGET_VM_MINUSER_ADDRESS (0x0000000000000000UL)
|
|
+#define TARGET_VM_MAXUSER_ADDRESS (0x0000008000000000UL)
|
|
+
|
|
+#define TARGET_USRSTACK (TARGET_VM_MAXUSER_ADDRESS - TARGET_PAGE_SIZE)
|
|
+
|
|
+struct target_ps_strings {
|
|
+ abi_ulong ps_argvstr;
|
|
+ uint32_t ps_nargvstr;
|
|
+ abi_ulong ps_envstr;
|
|
+ uint32_t ps_nenvstr;
|
|
+};
|
|
+
|
|
+#define TARGET_SPACE_USRSPACE 4096
|
|
+#define TARGET_ARG_MAX 262144
|
|
+
|
|
+#define TARGET_PS_STRINGS (TARGET_USRSTACK - sizeof(struct target_ps_strings))
|
|
+
|
|
+#else
|
|
+
|
|
+#define TARGET_USRSTACK 0
|
|
+#endif
|
|
+
|
|
+#endif /* _TARGET_VMPARAM_H_ */
|
|
diff --git a/bsd-user/mmap.c b/bsd-user/mmap.c
|
|
index 5d6cffc..9f42c27 100644
|
|
--- a/bsd-user/mmap.c
|
|
+++ b/bsd-user/mmap.c
|
|
@@ -275,7 +275,8 @@ unsigned long last_brk;
|
|
*/
|
|
/* page_init() marks pages used by the host as reserved to be sure not
|
|
to use them. */
|
|
-static abi_ulong mmap_find_vma(abi_ulong start, abi_ulong size)
|
|
+abi_ulong
|
|
+mmap_find_vma(abi_ulong start, abi_ulong size)
|
|
{
|
|
abi_ulong addr, addr1, addr_start;
|
|
int prot;
|
|
@@ -493,7 +494,7 @@ int target_munmap(abi_ulong start, abi_ulong len)
|
|
int prot, ret;
|
|
|
|
#ifdef DEBUG_MMAP
|
|
- printf("munmap: start=0x%lx len=0x%lx\n", start, len);
|
|
+ printf("munmap: start=0x" TARGET_FMT_lx " len=0x" TARGET_FMT_lx "\n", start, len);
|
|
#endif
|
|
if (start & ~TARGET_PAGE_MASK)
|
|
return -EINVAL;
|
|
diff --git a/bsd-user/qemu.h b/bsd-user/qemu.h
|
|
--- a/bsd-user/qemu.h
|
|
+++ b/bsd-user/qemu.h
|
|
@@ -20,9 +20,13 @@ enum BSDType {
|
|
};
|
|
extern enum BSDType bsd_type;
|
|
|
|
+abi_long memcpy_to_target(abi_ulong dest, const void *src,
|
|
+ unsigned long len);
|
|
+
|
|
#include "syscall_defs.h"
|
|
#include "syscall.h"
|
|
+#include "target_vmparam.h"
|
|
#include "target_signal.h"
|
|
#include "exec/gdbstub.h"
|
|
|
|
#if defined(CONFIG_USE_NPTL)
|
|
@@ -61,7 +65,7 @@ struct image_info {
|
|
|
|
struct sigqueue {
|
|
struct sigqueue *next;
|
|
- //target_siginfo_t info;
|
|
+ target_siginfo_t info;
|
|
};
|
|
|
|
struct emulated_sigtable {
|
|
@@ -88,6 +92,7 @@ typedef struct TaskState {
|
|
uint32_t stack_base;
|
|
#endif
|
|
struct image_info *info;
|
|
+ struct bsd_binprm *bprm;
|
|
|
|
struct emulated_sigtable sigtab[TARGET_NSIG];
|
|
struct sigqueue sigqueue_table[MAX_SIGQUEUE_SIZE]; /* siginfo queue */
|
|
@@ -98,6 +103,8 @@ typedef struct TaskState {
|
|
} __attribute__((aligned(16))) TaskState;
|
|
|
|
void init_task_state(TaskState *ts);
|
|
+void task_settid(TaskState *);
|
|
+void stop_all_tasks(void);
|
|
extern const char *qemu_uname_release;
|
|
#if defined(CONFIG_USE_GUEST_BASE)
|
|
extern unsigned long mmap_min_addr;
|
|
@@ -115,7 +122,7 @@ extern unsigned long mmap_min_addr;
|
|
* This structure is used to hold the arguments that are
|
|
* used when loading binaries.
|
|
*/
|
|
-struct linux_binprm {
|
|
+struct bsd_binprm {
|
|
char buf[128];
|
|
void *page[MAX_ARG_PAGES];
|
|
abi_ulong p;
|
|
@@ -125,21 +132,21 @@ struct linux_binprm {
|
|
char **argv;
|
|
char **envp;
|
|
char * filename; /* Name of binary */
|
|
+ int (*core_dump)(int, const CPUArchState *); /* coredump routine */
|
|
};
|
|
|
|
void do_init_thread(struct target_pt_regs *regs, struct image_info *infop);
|
|
abi_ulong loader_build_argptr(int envc, int argc, abi_ulong sp,
|
|
abi_ulong stringp, int push_ptr);
|
|
int loader_exec(const char * filename, char ** argv, char ** envp,
|
|
- struct target_pt_regs * regs, struct image_info *infop);
|
|
+ struct target_pt_regs * regs, struct image_info *infop,
|
|
+ struct bsd_binprm *);
|
|
|
|
-int load_elf_binary(struct linux_binprm * bprm, struct target_pt_regs * regs,
|
|
+int load_elf_binary(struct bsd_binprm * bprm, struct target_pt_regs * regs,
|
|
struct image_info * info);
|
|
-int load_flt_binary(struct linux_binprm * bprm, struct target_pt_regs * regs,
|
|
+int load_flt_binary(struct bsd_binprm * bprm, struct target_pt_regs * regs,
|
|
struct image_info * info);
|
|
|
|
-abi_long memcpy_to_target(abi_ulong dest, const void *src,
|
|
- unsigned long len);
|
|
void target_set_brk(abi_ulong new_brk);
|
|
abi_long do_brk(abi_ulong new_brk);
|
|
void syscall_init(void);
|
|
@@ -184,10 +191,12 @@ extern int do_strace;
|
|
/* signal.c */
|
|
void process_pending_signals(CPUArchState *cpu_env);
|
|
void signal_init(void);
|
|
-//int queue_signal(CPUArchState *env, int sig, target_siginfo_t *info);
|
|
-//void host_to_target_siginfo(target_siginfo_t *tinfo, const siginfo_t *info);
|
|
-//void target_to_host_siginfo(siginfo_t *info, const target_siginfo_t *tinfo);
|
|
-long do_sigreturn(CPUArchState *env);
|
|
+int queue_signal(CPUArchState *env, int sig, target_siginfo_t *info);
|
|
+void host_to_target_siginfo(target_siginfo_t *tinfo, const siginfo_t *info);
|
|
+void target_to_host_siginfo(siginfo_t *info, const target_siginfo_t *tinfo);
|
|
+int target_to_host_signal(int sig);
|
|
+int host_to_target_signal(int sig);
|
|
+long do_sigreturn(CPUArchState *env, abi_ulong uc_addr);
|
|
long do_rt_sigreturn(CPUArchState *env);
|
|
abi_long do_sigaltstack(abi_ulong uss_addr, abi_ulong uoss_addr, abi_ulong sp);
|
|
|
|
@@ -203,6 +212,7 @@ int target_msync(abi_ulong start, abi_ul
|
|
extern unsigned long last_brk;
|
|
void mmap_lock(void);
|
|
void mmap_unlock(void);
|
|
+abi_ulong mmap_find_vma(abi_ulong, abi_ulong);
|
|
void cpu_list_lock(void);
|
|
void cpu_list_unlock(void);
|
|
#if defined(CONFIG_USE_NPTL)
|
|
diff --git a/bsd-user/signal.c b/bsd-user/signal.c
|
|
index 445f69e..0502a6a 100644
|
|
--- a/bsd-user/signal.c
|
|
+++ b/bsd-user/signal.c
|
|
@@ -2,6 +2,7 @@
|
|
* Emulation of BSD signals
|
|
*
|
|
* Copyright (c) 2003 - 2008 Fabrice Bellard
|
|
+ * Copyright (c) 2012 Stacey 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
|
|
@@ -23,16 +24,1218 @@
|
|
#include <unistd.h>
|
|
#include <signal.h>
|
|
#include <errno.h>
|
|
+#include <sys/types.h>
|
|
+#include <sys/time.h>
|
|
+#include <sys/resource.h>
|
|
|
|
#include "qemu.h"
|
|
#include "target_signal.h"
|
|
|
|
-//#define DEBUG_SIGNAL
|
|
+// #define DEBUG_SIGNAL
|
|
|
|
-void signal_init(void)
|
|
+#ifndef _NSIG
|
|
+#define _NSIG 128
|
|
+#endif
|
|
+
|
|
+static target_stack_t target_sigaltstack_used = {
|
|
+ .ss_sp = 0,
|
|
+ .ss_size = 0,
|
|
+ .ss_flags = TARGET_SS_DISABLE,
|
|
+};
|
|
+
|
|
+static uint8_t host_to_target_signal_table[_NSIG] = {
|
|
+ [SIGHUP] = TARGET_SIGHUP,
|
|
+ [SIGINT] = TARGET_SIGINT,
|
|
+ [SIGQUIT] = TARGET_SIGQUIT,
|
|
+ [SIGILL] = TARGET_SIGILL,
|
|
+ [SIGTRAP] = TARGET_SIGTRAP,
|
|
+ [SIGABRT] = TARGET_SIGABRT,
|
|
+ /* [SIGIOT] = TARGET_SIGIOT, */
|
|
+ [SIGEMT] = TARGET_SIGEMT,
|
|
+ [SIGFPE] = TARGET_SIGFPE,
|
|
+ [SIGKILL] = TARGET_SIGKILL,
|
|
+ [SIGBUS] = TARGET_SIGBUS,
|
|
+ [SIGSEGV] = TARGET_SIGSEGV,
|
|
+ [SIGSYS] = TARGET_SIGSYS,
|
|
+ [SIGPIPE] = TARGET_SIGPIPE,
|
|
+ [SIGALRM] = TARGET_SIGALRM,
|
|
+ [SIGTERM] = TARGET_SIGTERM,
|
|
+ [SIGURG] = TARGET_SIGURG,
|
|
+ [SIGSTOP] = TARGET_SIGSTOP,
|
|
+ [SIGTSTP] = TARGET_SIGTSTP,
|
|
+ [SIGCONT] = TARGET_SIGCONT,
|
|
+ [SIGCHLD] = TARGET_SIGCHLD,
|
|
+ [SIGTTIN] = TARGET_SIGTTIN,
|
|
+ [SIGTTOU] = TARGET_SIGTTOU,
|
|
+ [SIGIO] = TARGET_SIGIO,
|
|
+ [SIGXCPU] = TARGET_SIGXCPU,
|
|
+ [SIGXFSZ] = TARGET_SIGXFSZ,
|
|
+ [SIGVTALRM] = TARGET_SIGVTALRM,
|
|
+ [SIGPROF] = TARGET_SIGPROF,
|
|
+ [SIGWINCH] = TARGET_SIGWINCH,
|
|
+ [SIGINFO] = TARGET_SIGINFO,
|
|
+ [SIGUSR1] = TARGET_SIGUSR1,
|
|
+ [SIGUSR2] = TARGET_SIGUSR2,
|
|
+#ifdef SIGTHR
|
|
+ [SIGTHR] = TARGET_SIGTHR,
|
|
+#endif
|
|
+ /* [SIGLWP] = TARGET_SIGLWP, */
|
|
+#ifdef SIGLIBRT
|
|
+ [SIGLIBRT] = TARGET_SIGLIBRT,
|
|
+#endif
|
|
+
|
|
+ /*
|
|
+ * The following signals stay the same.
|
|
+ * Nasty hack: Reverse SIGRTMIN and SIGRTMAX to avoid overlap with
|
|
+ * host libpthread signals. This assumes no one actually uses
|
|
+ * SIGRTMAX. To fix this properly we need to manual signal delivery
|
|
+ * multiplexed over a single host signal.
|
|
+ */
|
|
+ [SIGRTMIN] = SIGRTMAX,
|
|
+ [SIGRTMAX] = SIGRTMIN,
|
|
+};
|
|
+
|
|
+static uint8_t target_to_host_signal_table[_NSIG];
|
|
+
|
|
+static struct target_sigaction sigact_table[TARGET_NSIG];
|
|
+
|
|
+static void host_signal_handler(int host_signum, siginfo_t *info, void *puc);
|
|
+
|
|
+static inline int
|
|
+on_sig_stack(unsigned long sp)
|
|
+{
|
|
+ return (sp - target_sigaltstack_used.ss_sp
|
|
+ < target_sigaltstack_used.ss_size);
|
|
+}
|
|
+
|
|
+static inline int
|
|
+sas_ss_flags(unsigned long sp)
|
|
+{
|
|
+ return (target_sigaltstack_used.ss_size == 0 ? SS_DISABLE
|
|
+ : on_sig_stack(sp) ? SS_ONSTACK : 0);
|
|
+}
|
|
+
|
|
+int
|
|
+host_to_target_signal(int sig)
|
|
+{
|
|
+
|
|
+ if (sig >= _NSIG)
|
|
+ return (sig);
|
|
+ return (host_to_target_signal_table[sig]);
|
|
+}
|
|
+
|
|
+int
|
|
+target_to_host_signal(int sig)
|
|
+{
|
|
+
|
|
+ if (sig >= _NSIG)
|
|
+ return (sig);
|
|
+ return (target_to_host_signal_table[sig]);
|
|
+}
|
|
+
|
|
+static inline void
|
|
+target_sigemptyset(target_sigset_t *set)
|
|
{
|
|
+ memset(set, 0, sizeof(*set));
|
|
}
|
|
|
|
-void process_pending_signals(CPUArchState *cpu_env)
|
|
+static inline void
|
|
+target_sigaddset(target_sigset_t *set, int signum)
|
|
{
|
|
+ signum--;
|
|
+ uint32_t mask = (uint32_t)1 << (signum % TARGET_NSIG_BPW);
|
|
+ set->__bits[signum / TARGET_NSIG_BPW] |= mask;
|
|
+}
|
|
+
|
|
+static inline int
|
|
+target_sigismember(const target_sigset_t *set, int signum)
|
|
+{
|
|
+ signum--;
|
|
+ abi_ulong mask = (abi_ulong)1 << (signum % TARGET_NSIG_BPW);
|
|
+ return ((set->__bits[signum / TARGET_NSIG_BPW] & mask) != 0);
|
|
+}
|
|
+
|
|
+static void
|
|
+host_to_target_sigset_internal(target_sigset_t *d, const sigset_t *s)
|
|
+{
|
|
+ int i;
|
|
+
|
|
+ target_sigemptyset(d);
|
|
+ for (i = 1; i <= TARGET_NSIG; i++) {
|
|
+ if (sigismember(s, i)) {
|
|
+ target_sigaddset(d, host_to_target_signal(i));
|
|
+ }
|
|
+ }
|
|
+}
|
|
+
|
|
+void
|
|
+host_to_target_sigset(target_sigset_t *d, const sigset_t *s)
|
|
+{
|
|
+ target_sigset_t d1;
|
|
+ int i;
|
|
+
|
|
+ host_to_target_sigset_internal(&d1, s);
|
|
+ for(i = 0;i < TARGET_NSIG_WORDS; i++)
|
|
+ d->__bits[i] = tswap32(d1.__bits[i]);
|
|
+}
|
|
+
|
|
+static void
|
|
+target_to_host_sigset_internal(sigset_t *d, const target_sigset_t *s)
|
|
+{
|
|
+ int i;
|
|
+
|
|
+ sigemptyset(d);
|
|
+ for (i = 1; i <= TARGET_NSIG; i++) {
|
|
+ if (target_sigismember(s, i)) {
|
|
+ sigaddset(d, target_to_host_signal(i));
|
|
+ }
|
|
+ }
|
|
+}
|
|
+
|
|
+void
|
|
+target_to_host_sigset(sigset_t *d, const target_sigset_t *s)
|
|
+{
|
|
+ target_sigset_t s1;
|
|
+ int i;
|
|
+
|
|
+ for(i = 0; i < TARGET_NSIG_WORDS; i++)
|
|
+ s1.__bits[i] = tswap32(s->__bits[i]);
|
|
+ target_to_host_sigset_internal(d, &s1);
|
|
+}
|
|
+
|
|
+/* Siginfo conversion. */
|
|
+static inline void
|
|
+host_to_target_siginfo_noswap(target_siginfo_t *tinfo, const siginfo_t *info)
|
|
+{
|
|
+ int sig;
|
|
+
|
|
+ sig = host_to_target_signal(info->si_signo);
|
|
+ tinfo->si_signo = sig;
|
|
+ tinfo->si_errno = info->si_errno;
|
|
+ tinfo->si_code = info->si_code;
|
|
+ tinfo->si_pid = info->si_pid;
|
|
+ tinfo->si_uid = info->si_uid;
|
|
+ tinfo->si_addr = (abi_ulong)(unsigned long)info->si_addr;
|
|
+ /* si_value is opaque to kernel */
|
|
+ tinfo->si_value.sival_ptr =
|
|
+ (abi_ulong)(unsigned long)info->si_value.sival_ptr;
|
|
+ if (SIGILL == sig || SIGFPE == sig || SIGSEGV == sig ||
|
|
+ SIGBUS == sig || SIGTRAP == sig) {
|
|
+ tinfo->_reason._fault._trapno = info->_reason._fault._trapno;
|
|
+#ifdef SIGPOLL
|
|
+ } else if (SIGPOLL == sig) {
|
|
+ tinfo->_reason._poll._band = info->_reason._poll._band;
|
|
+#endif
|
|
+ } else {
|
|
+ tinfo->_reason._timer._timerid = info->_reason._timer._timerid;
|
|
+ tinfo->_reason._timer._overrun = info->_reason._timer._overrun;
|
|
+ }
|
|
+}
|
|
+
|
|
+static void
|
|
+tswap_siginfo(target_siginfo_t *tinfo, const target_siginfo_t *info)
|
|
+{
|
|
+ int sig;
|
|
+ sig = info->si_signo;
|
|
+ tinfo->si_signo = tswap32(sig);
|
|
+ tinfo->si_errno = tswap32(info->si_errno);
|
|
+ tinfo->si_code = tswap32(info->si_code);
|
|
+ tinfo->si_pid = tswap32(info->si_pid);
|
|
+ tinfo->si_uid = tswap32(info->si_uid);
|
|
+ tinfo->si_addr = tswapal(info->si_addr);
|
|
+ if (SIGILL == sig || SIGFPE == sig || SIGSEGV == sig ||
|
|
+ SIGBUS == sig || SIGTRAP == sig) {
|
|
+ tinfo->_reason._fault._trapno =
|
|
+ tswap32(info->_reason._fault._trapno);
|
|
+#ifdef SIGPOLL
|
|
+ } else if (SIGPOLL == sig) {
|
|
+ tinfo->_reason._poll._band = tswap32(info->_reason._poll._band);
|
|
+#endif
|
|
+ } else {
|
|
+ tinfo->_reason._timer._timerid =
|
|
+ tswap32(info->_reason._timer._timerid);
|
|
+ tinfo->_reason._timer._overrun =
|
|
+ tswap32(info->_reason._timer._overrun);
|
|
+ }
|
|
+}
|
|
+
|
|
+void
|
|
+host_to_target_siginfo(target_siginfo_t *tinfo, const siginfo_t *info)
|
|
+{
|
|
+
|
|
+ host_to_target_siginfo_noswap(tinfo, info);
|
|
+ tswap_siginfo(tinfo, tinfo);
|
|
+}
|
|
+
|
|
+/* Returns 1 if given signal should dump core if not handled. */
|
|
+static int
|
|
+core_dump_signal(int sig)
|
|
+{
|
|
+ switch (sig) {
|
|
+ case TARGET_SIGABRT:
|
|
+ case TARGET_SIGFPE:
|
|
+ case TARGET_SIGILL:
|
|
+ case TARGET_SIGQUIT:
|
|
+ case TARGET_SIGSEGV:
|
|
+ case TARGET_SIGTRAP:
|
|
+ case TARGET_SIGBUS:
|
|
+ return (1);
|
|
+ default:
|
|
+ return (0);
|
|
+ }
|
|
+}
|
|
+
|
|
+/* Signal queue handling. */
|
|
+static inline struct sigqueue *
|
|
+alloc_sigqueue(CPUArchState *env)
|
|
+{
|
|
+ TaskState *ts = env->opaque;
|
|
+ struct sigqueue *q = ts->first_free;
|
|
+
|
|
+ if (!q)
|
|
+ return (NULL);
|
|
+ ts->first_free = q->next;
|
|
+ return (q);
|
|
+}
|
|
+
|
|
+static inline void
|
|
+free_sigqueue(CPUArchState *env, struct sigqueue *q)
|
|
+{
|
|
+
|
|
+ TaskState *ts = env->opaque;
|
|
+ q->next = ts->first_free;
|
|
+ ts->first_free = q;
|
|
+}
|
|
+
|
|
+/* Abort execution with signal. */
|
|
+static void QEMU_NORETURN
|
|
+force_sig(int target_sig)
|
|
+{
|
|
+ TaskState *ts = (TaskState *)thread_env->opaque;
|
|
+ int host_sig, core_dumped = 0;
|
|
+ struct sigaction act;
|
|
+
|
|
+ host_sig = target_to_host_signal(target_sig);
|
|
+ gdb_signalled(thread_env, target_sig);
|
|
+
|
|
+ /* Dump core if supported by target binary format */
|
|
+ if (core_dump_signal(target_sig) && (ts->bprm->core_dump != NULL)) {
|
|
+ stop_all_tasks();
|
|
+ core_dumped =
|
|
+ ((*ts->bprm->core_dump)(target_sig, thread_env) == 0);
|
|
+ }
|
|
+ if (core_dumped) {
|
|
+ struct rlimit nodump;
|
|
+
|
|
+ /*
|
|
+ * We already dumped the core of target process, we don't want
|
|
+ * a coredump of qemu itself.
|
|
+ */
|
|
+ getrlimit(RLIMIT_CORE, &nodump);
|
|
+ nodump.rlim_cur = 0;
|
|
+ (void) fprintf(stderr, "qemu: uncaught target signal %d (%s) "
|
|
+ "- %s\n", target_sig, strsignal(host_sig), "core dumped");
|
|
+ }
|
|
+
|
|
+ /*
|
|
+ * The proper exit code for dying from an uncaught signal is
|
|
+ * -<signal>. The kernel doesn't allow exit() or _exit() to pass
|
|
+ * a negative value. To get the proper exit code we need to
|
|
+ * actually die from an uncaught signal. Here the default signal
|
|
+ * handler is installed, we send ourself a signal and we wait for
|
|
+ * it to arrive.
|
|
+ */
|
|
+ memset(&act, 0, sizeof(act));
|
|
+ sigfillset(&act.sa_mask);
|
|
+ act.sa_handler = SIG_DFL;
|
|
+ sigaction(host_sig, &act, NULL);
|
|
+
|
|
+ kill(getpid(), host_sig);
|
|
+
|
|
+ /*
|
|
+ * Make sure the signal isn't masked (just reuse the mask inside
|
|
+ * of act).
|
|
+ */
|
|
+ sigdelset(&act.sa_mask, host_sig);
|
|
+ sigsuspend(&act.sa_mask);
|
|
+
|
|
+ /* unreachable */
|
|
+ abort();
|
|
+}
|
|
+
|
|
+/*
|
|
+ * Queue a signal so that it will be send to the virtual CPU as soon as
|
|
+ * possible.
|
|
+ */
|
|
+int
|
|
+queue_signal(CPUArchState *env, int sig, target_siginfo_t *info)
|
|
+{
|
|
+ TaskState *ts = env->opaque;
|
|
+ struct emulated_sigtable *k;
|
|
+ struct sigqueue *q, **pq;
|
|
+ abi_ulong handler;
|
|
+ int queue;
|
|
+
|
|
+ k = &ts->sigtab[sig - 1];
|
|
+ queue = gdb_queuesig ();
|
|
+ handler = sigact_table[sig - 1]._sa_handler;
|
|
+#ifdef DEBUG_SIGNAL
|
|
+ fprintf(stderr, "queue_signal: sig=%d handler=0x%lx flags=0x%x\n", sig,
|
|
+ handler, (uint32_t)sigact_table[sig - 1].sa_flags);
|
|
+#endif
|
|
+ if (!queue && (TARGET_SIG_DFL == handler)) {
|
|
+ if (sig == TARGET_SIGTSTP || sig == TARGET_SIGTTIN ||
|
|
+ sig == TARGET_SIGTTOU) {
|
|
+ kill(getpid(), SIGSTOP);
|
|
+ return (0);
|
|
+ } else {
|
|
+ if (sig != TARGET_SIGCHLD &&
|
|
+ sig != TARGET_SIGURG &&
|
|
+ sig != TARGET_SIGWINCH &&
|
|
+ sig != TARGET_SIGCONT) {
|
|
+ force_sig(sig);
|
|
+ } else {
|
|
+ return (0); /* The signal was ignored. */
|
|
+ }
|
|
+ }
|
|
+ } else if (!queue && (TARGET_SIG_IGN == handler)) {
|
|
+ return (0); /* Ignored signal. */
|
|
+ } else if (!queue && (TARGET_SIG_ERR == handler)) {
|
|
+ force_sig(sig);
|
|
+ } else {
|
|
+ pq = &k->first;
|
|
+
|
|
+ /*
|
|
+ * FreeBSD signals are always queued.
|
|
+ * Linux only queues real time signals.
|
|
+ * XXX this code is not thread safe.
|
|
+ */
|
|
+ if (!k->pending) {
|
|
+ /* first signal */
|
|
+ q = &k->info;
|
|
+ } else {
|
|
+ q = alloc_sigqueue(env);
|
|
+ if (!q)
|
|
+ return (-EAGAIN);
|
|
+ while (*pq != NULL)
|
|
+ pq = &(*pq)->next;
|
|
+ }
|
|
+ *pq = q;
|
|
+ q->info = *info;
|
|
+ q->next = NULL;
|
|
+ k->pending = 1;
|
|
+ /* Signal that a new signal is pending. */
|
|
+ ts->signal_pending = 1;
|
|
+ return (1); /* Indicates that the signal was queued. */
|
|
+ }
|
|
+}
|
|
+
|
|
+static void
|
|
+host_signal_handler(int host_signum, siginfo_t *info, void *puc)
|
|
+{
|
|
+ int sig;
|
|
+ target_siginfo_t tinfo;
|
|
+
|
|
+ /*
|
|
+ * The CPU emulator uses some host signal to detect exceptions so
|
|
+ * we forward to it some signals.
|
|
+ */
|
|
+ if ((host_signum == SIGSEGV || host_signum == SIGBUS) &&
|
|
+ info->si_code > 0) {
|
|
+ if (cpu_signal_handler(host_signum, info, puc))
|
|
+ return;
|
|
+ }
|
|
+
|
|
+ /* Get the target signal number. */
|
|
+ sig = host_to_target_signal(host_signum);
|
|
+ if (sig < 1 || sig > TARGET_NSIG)
|
|
+ return;
|
|
+#ifdef DEBUG_SIGNAL
|
|
+ fprintf(stderr, "qemu: got signal %d\n", sig);
|
|
+#endif
|
|
+ host_to_target_siginfo_noswap(&tinfo, info);
|
|
+ if (queue_signal(thread_env, sig, &tinfo) == 1) {
|
|
+ /* Interrupt the virtual CPU as soon as possible. */
|
|
+ cpu_exit(thread_env);
|
|
+ }
|
|
+}
|
|
+
|
|
+/* do_sigaltstack() returns target values and errnos. */
|
|
+/* compare to kern/kern_sig.c sys_sigaltstack() and kern_sigaltstack() */
|
|
+abi_long
|
|
+do_sigaltstack(abi_ulong uss_addr, abi_ulong uoss_addr, abi_ulong sp)
|
|
+{
|
|
+ int ret = 0;
|
|
+ target_stack_t ss, oss, *uss;
|
|
+
|
|
+ if (uoss_addr) {
|
|
+ /* Save current signal stack params */
|
|
+ oss.ss_sp = tswapl(target_sigaltstack_used.ss_sp);
|
|
+ oss.ss_size = tswapl(target_sigaltstack_used.ss_size);
|
|
+ oss.ss_flags = tswapl(sas_ss_flags(sp));
|
|
+ }
|
|
+
|
|
+ if (uss_addr) {
|
|
+
|
|
+ if (!lock_user_struct(VERIFY_READ, uss, uss_addr, 1) ||
|
|
+ __get_user(ss.ss_sp, &uss->ss_sp) ||
|
|
+ __get_user(ss.ss_size, &uss->ss_size) ||
|
|
+ __get_user(ss.ss_flags, &uss->ss_flags)) {
|
|
+ ret = -TARGET_EFAULT;
|
|
+ goto out;
|
|
+ }
|
|
+ unlock_user_struct(uss, uss_addr, 0);
|
|
+
|
|
+ if (on_sig_stack(sp)) {
|
|
+ ret = -TARGET_EPERM;
|
|
+ goto out;
|
|
+ }
|
|
+
|
|
+ if ((ss.ss_flags & ~TARGET_SS_DISABLE) != 0) {
|
|
+ ret = -TARGET_EINVAL;
|
|
+ goto out;
|
|
+ }
|
|
+
|
|
+ if (!(ss.ss_flags & ~TARGET_SS_DISABLE)) {
|
|
+ if (ss.ss_size < TARGET_MINSIGSTKSZ) {
|
|
+ ret = -TARGET_ENOMEM;
|
|
+ goto out;
|
|
+ }
|
|
+ } else {
|
|
+ ss.ss_size = 0;
|
|
+ ss.ss_sp = 0;
|
|
+ }
|
|
+
|
|
+ target_sigaltstack_used.ss_sp = ss.ss_sp;
|
|
+ target_sigaltstack_used.ss_size = ss.ss_size;
|
|
+ }
|
|
+
|
|
+ if (uoss_addr) {
|
|
+ /* Copy out to user saved signal stack params */
|
|
+ if (copy_to_user(uoss_addr, &oss, sizeof(oss))) {
|
|
+ ret = -TARGET_EFAULT;
|
|
+ goto out;
|
|
+ }
|
|
+ }
|
|
+
|
|
+out:
|
|
+ return (ret);
|
|
+}
|
|
+
|
|
+static int
|
|
+fatal_signal(int sig)
|
|
+{
|
|
+
|
|
+ switch (sig) {
|
|
+ case TARGET_SIGCHLD:
|
|
+ case TARGET_SIGURG:
|
|
+ case TARGET_SIGWINCH:
|
|
+ /* Ignored by default. */
|
|
+ return (0);
|
|
+ case TARGET_SIGCONT:
|
|
+ case TARGET_SIGSTOP:
|
|
+ case TARGET_SIGTSTP:
|
|
+ case TARGET_SIGTTIN:
|
|
+ case TARGET_SIGTTOU:
|
|
+ /* Job control signals. */
|
|
+ return (0);
|
|
+ default:
|
|
+ return (1);
|
|
+ }
|
|
+}
|
|
+
|
|
+/* do_sigaction() return host values and errnos */
|
|
+int
|
|
+do_sigaction(int sig, const struct target_sigaction *act,
|
|
+ struct target_sigaction *oact)
|
|
+{
|
|
+ struct target_sigaction *k;
|
|
+ struct sigaction act1;
|
|
+ int host_sig;
|
|
+ int ret = 0;
|
|
+
|
|
+ if (sig < 1 || sig > TARGET_NSIG || TARGET_SIGKILL == sig ||
|
|
+ TARGET_SIGSTOP == sig)
|
|
+ return (-EINVAL);
|
|
+ k = &sigact_table[sig - 1];
|
|
+#if defined(DEBUG_SIGNAL)
|
|
+ fprintf(stderr, "do_sigaction sig=%d act=%p, oact=%p\n",
|
|
+ sig, act, oact);
|
|
+#endif
|
|
+ if (oact) {
|
|
+ oact->_sa_handler = tswapal(k->_sa_handler);
|
|
+ oact->sa_flags = tswap32(k->sa_flags);
|
|
+ oact->sa_mask = k->sa_mask;
|
|
+ }
|
|
+ if (act) {
|
|
+ /* XXX: this is most likely not threadsafe. */
|
|
+ k->_sa_handler = tswapal(act->_sa_handler);
|
|
+ k->sa_flags = tswap32(act->sa_flags);
|
|
+ k->sa_mask = act->sa_mask;
|
|
+
|
|
+ /* Update the host signal state. */
|
|
+ host_sig = target_to_host_signal(sig);
|
|
+ if (host_sig != SIGSEGV && host_sig != SIGBUS) {
|
|
+ memset(&act1, 0, sizeof(struct sigaction));
|
|
+ sigfillset(&act1.sa_mask);
|
|
+ if (k->sa_flags & TARGET_SA_RESTART)
|
|
+ act1.sa_flags |= SA_RESTART;
|
|
+ /*
|
|
+ * Note: It is important to update the host kernel
|
|
+ * signal mask to avoid getting unexpected interrupted
|
|
+ * system calls.
|
|
+ */
|
|
+ if (k->_sa_handler == TARGET_SIG_IGN) {
|
|
+ act1.sa_sigaction = (void *)SIG_IGN;
|
|
+ } else if (k->_sa_handler == TARGET_SIG_DFL) {
|
|
+ if (fatal_signal(sig))
|
|
+ act1.sa_sigaction =
|
|
+ host_signal_handler;
|
|
+ else
|
|
+ act1.sa_sigaction = (void *)SIG_DFL;
|
|
+ } else {
|
|
+ act1.sa_flags = SA_SIGINFO;
|
|
+ act1.sa_sigaction = host_signal_handler;
|
|
+ }
|
|
+ ret = sigaction(host_sig, &act1, NULL);
|
|
+#if defined(DEBUG_SIGNAL)
|
|
+ fprintf(stderr, "sigaction (action = %p (host_signal_handler = %p)) returned: %d\n", act1.sa_sigaction, host_signal_handler, ret);
|
|
+#endif
|
|
+ }
|
|
+ }
|
|
+ return (ret);
|
|
+}
|
|
+
|
|
+#if defined(TARGET_MIPS64)
|
|
+static inline int
|
|
+restore_sigmcontext(CPUMIPSState *regs, target_mcontext_t *mc)
|
|
+{
|
|
+ int i, err = 0;
|
|
+
|
|
+ for(i = 1; i < 32; i++)
|
|
+ err |= __get_user(regs->active_tc.gpr[i],
|
|
+ &mc->mc_regs[i]);
|
|
+ err |= __get_user(regs->CP0_EPC, &mc->mc_pc);
|
|
+ err |= __get_user(regs->active_tc.LO[0], &mc->mullo);
|
|
+ err |= __get_user(regs->active_tc.HI[0], &mc->mulhi);
|
|
+ err |= __get_user(regs->tls_value, &mc->mc_tls); /* XXX thread tls */
|
|
+
|
|
+#if 0 /* XXX */
|
|
+ int used_fp = 0;
|
|
+
|
|
+ err |= __get_user(used_fp, &mc->mc_fpused);
|
|
+ conditional_used_math(used_fp);
|
|
+
|
|
+ preempt_disabled();
|
|
+ if (used_math()) {
|
|
+ /* restore fpu context if we have used it before */
|
|
+ own_fpu();
|
|
+ err |= restore_fp_context(mc);
|
|
+ } else {
|
|
+ /* signal handler may have used FPU. Give it up. */
|
|
+ lose_fpu();
|
|
+ }
|
|
+ preempt_enable();
|
|
+#endif
|
|
+
|
|
+ return (err);
|
|
+}
|
|
+
|
|
+static inline int
|
|
+setup_sigmcontext(CPUMIPSState *regs, target_mcontext_t *mc, int32_t oonstack)
|
|
+{
|
|
+ int i, err = 0;
|
|
+ abi_long ucontext_magic = TARGET_UCONTEXT_MAGIC;
|
|
+
|
|
+ err = __put_user(oonstack ? 1 : 0, &mc->mc_onstack);
|
|
+ err |= __put_user(regs->active_tc.PC, &mc->mc_pc);
|
|
+ err |= __put_user(regs->active_tc.LO[0], &mc->mullo);
|
|
+ err |= __put_user(regs->active_tc.HI[0], &mc->mulhi);
|
|
+ err |= __put_user(regs->tls_value, &mc->mc_tls); /* XXX thread tls */
|
|
+
|
|
+ err |= __put_user(ucontext_magic, &mc->mc_regs[0]);
|
|
+ for(i = 1; i < 32; i++)
|
|
+ err |= __put_user(regs->active_tc.gpr[i], &mc->mc_regs[i]);
|
|
+
|
|
+ err |= __put_user(0, &mc->mc_fpused);
|
|
+
|
|
+#if 0 /* XXX */
|
|
+ err |= __put_user(used_math(), &mc->mc_fpused);
|
|
+ if (used_math())
|
|
+ goto out;
|
|
+
|
|
+ /*
|
|
+ * Save FPU state to signal context. Signal handler will "inherit"
|
|
+ * current FPU state.
|
|
+ */
|
|
+ preempt_disable();
|
|
+
|
|
+ if (!is_fpu_owner()) {
|
|
+ own_fpu();
|
|
+ for(i = 0; i < 33; i++)
|
|
+ err |= __put_user(regs->active_tc.fpregs[i], &mc->mc_fpregs[i]);
|
|
+ }
|
|
+ err |= save_fp_context(fg);
|
|
+
|
|
+ preempt_enable();
|
|
+out:
|
|
+#endif
|
|
+ return (err);
|
|
+}
|
|
+
|
|
+static inline abi_ulong
|
|
+get_sigframe(struct target_sigaction *ka, CPUMIPSState *regs, size_t frame_size)
|
|
+{
|
|
+ abi_ulong sp;
|
|
+
|
|
+ /* Use default user stack */
|
|
+ sp = regs->active_tc.gpr[29];
|
|
+
|
|
+ if ((ka->sa_flags & TARGET_SA_ONSTACK) && (sas_ss_flags(sp) == 0)) {
|
|
+ sp = target_sigaltstack_used.ss_sp + target_sigaltstack_used.ss_size;
|
|
+ }
|
|
+
|
|
+ return ((sp - frame_size) & ~7);
|
|
+}
|
|
+
|
|
+/* compare to mips/mips/pm_machdep.c sendsig() */
|
|
+static void setup_frame(int sig, struct target_sigaction *ka,
|
|
+ target_sigset_t *set, CPUMIPSState *regs)
|
|
+{
|
|
+ struct target_sigframe *frame;
|
|
+ abi_ulong frame_addr;
|
|
+ int i;
|
|
+
|
|
+#ifdef DEBUG_SIGNAL
|
|
+ fprintf(stderr, "setup_frame()\n");
|
|
+#endif
|
|
+
|
|
+ frame_addr = get_sigframe(ka, regs, sizeof(*frame));
|
|
+ if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0))
|
|
+ goto give_sigsegv;
|
|
+
|
|
+ if (setup_sigmcontext(regs, &frame->sf_uc.uc_mcontext,
|
|
+ ! on_sig_stack(frame_addr)))
|
|
+ goto give_sigsegv;
|
|
+
|
|
+ for(i = 0; i < TARGET_NSIG_WORDS; i++) {
|
|
+ if (__put_user(set->__bits[i], &frame->sf_uc.uc_sigmask.__bits[i]))
|
|
+ goto give_sigsegv;
|
|
+ }
|
|
+
|
|
+ /* fill in sigframe structure */
|
|
+ if (__put_user(sig, &frame->sf_signum))
|
|
+ goto give_sigsegv;
|
|
+ if (__put_user(0, &frame->sf_siginfo))
|
|
+ goto give_sigsegv;
|
|
+ if (__put_user(0, &frame->sf_ucontext))
|
|
+ goto give_sigsegv;
|
|
+
|
|
+ /* fill in siginfo structure */
|
|
+ if (__put_user(sig, &frame->sf_si.si_signo))
|
|
+ goto give_sigsegv;
|
|
+ if (__put_user(TARGET_SA_SIGINFO, &frame->sf_si.si_code))
|
|
+ goto give_sigsegv;
|
|
+ if (__put_user(regs->CP0_BadVAddr, &frame->sf_si.si_addr))
|
|
+ goto give_sigsegv;
|
|
+
|
|
+ /*
|
|
+ * Arguments to signal handler:
|
|
+ * a0 ($4) = signal number
|
|
+ * a1 ($5) = siginfo pointer
|
|
+ * a2 ($6) = ucontext pointer
|
|
+ * PC = signal handler pointer
|
|
+ * t9 ($25) = signal handler pointer
|
|
+ * $29 = point to sigframe struct
|
|
+ * ra ($31) = sigtramp at base of user stack
|
|
+ */
|
|
+ regs->active_tc.gpr[ 4] = sig;
|
|
+ regs->active_tc.gpr[ 5] = frame_addr +
|
|
+ offsetof(struct target_sigframe, sf_si);
|
|
+ regs->active_tc.gpr[ 6] = frame_addr +
|
|
+ offsetof(struct target_sigframe, sf_uc);
|
|
+ regs->active_tc.gpr[25] = regs->active_tc.PC = ka->_sa_handler;
|
|
+ regs->active_tc.gpr[29] = frame_addr;
|
|
+ regs->active_tc.gpr[31] = TARGET_PS_STRINGS - TARGET_SZSIGCODE;
|
|
+ unlock_user_struct(frame, frame_addr, 1);
|
|
+ return;
|
|
+
|
|
+give_sigsegv:
|
|
+ unlock_user_struct(frame, frame_addr, 1);
|
|
+ force_sig(TARGET_SIGSEGV);
|
|
+}
|
|
+
|
|
+long
|
|
+do_sigreturn(CPUMIPSState *regs, abi_ulong uc_addr)
|
|
+{
|
|
+ target_ucontext_t *ucontext;
|
|
+ sigset_t blocked;
|
|
+ target_sigset_t target_set;
|
|
+ int i;
|
|
+
|
|
+#if defined(DEBUG_SIGNAL)
|
|
+ fprintf(stderr, "do_sigreturn\n");
|
|
+#endif
|
|
+ if (!lock_user_struct(VERIFY_READ, ucontext, uc_addr, 1))
|
|
+ goto badframe;
|
|
+
|
|
+ for(i = 0; i < TARGET_NSIG_WORDS; i++) {
|
|
+ if (__get_user(target_set.__bits[i], &ucontext->uc_sigmask.__bits[i]))
|
|
+ goto badframe;
|
|
+ }
|
|
+
|
|
+ if (restore_sigmcontext(regs, &ucontext->uc_mcontext))
|
|
+ goto badframe;
|
|
+
|
|
+ target_to_host_sigset_internal(&blocked, &target_set);
|
|
+ sigprocmask(SIG_SETMASK, &blocked, NULL);
|
|
+
|
|
+ regs->active_tc.PC = regs->CP0_EPC;
|
|
+ regs->CP0_EPC = 0; /* XXX for nested signals ? */
|
|
+ return (-TARGET_QEMU_ESIGRETURN);
|
|
+
|
|
+badframe:
|
|
+ force_sig(TARGET_SIGSEGV);
|
|
+ return (0);
|
|
+}
|
|
+
|
|
+#elif defined(TARGET_SPARC64)
|
|
+
|
|
+extern abi_ulong sparc_user_sigtramp;
|
|
+
|
|
+#define mc_flags mc_global[0]
|
|
+#define mc_sp mc_out[6]
|
|
+#define mc_fprs mc_local[0]
|
|
+#define mc_fsr mc_local[1]
|
|
+#define mc_qsr mc_local[2]
|
|
+#define mc_tnpc mc_in[0]
|
|
+#define mc_tpc mc_in[1]
|
|
+#define mc_tstate mc_in[2]
|
|
+#define mc_y mc_in[4]
|
|
+#define mc_wstate mc_in[5]
|
|
+
|
|
+#define ureg_i0 regwptr[0 ]
|
|
+#define ureg_i1 regwptr[1 ]
|
|
+#define ureg_i2 regwptr[2 ]
|
|
+#define ureg_i3 regwptr[3 ]
|
|
+#define ureg_i4 regwptr[4 ]
|
|
+#define ureg_i5 regwptr[5 ]
|
|
+#define ureg_i6 regwptr[6 ]
|
|
+#define ureg_i7 regwptr[7 ]
|
|
+#define ureg_l0 regwptr[8 ]
|
|
+#define ureg_l1 regwptr[9 ]
|
|
+#define ureg_l2 regwptr[10]
|
|
+#define ureg_l3 regwptr[11]
|
|
+#define ureg_l4 regwptr[12]
|
|
+#define ureg_l5 regwptr[13]
|
|
+#define ureg_l6 regwptr[14]
|
|
+#define ureg_l7 regwptr[15]
|
|
+#define ureg_o0 regwptr[16]
|
|
+#define ureg_o1 regwptr[17]
|
|
+#define ureg_o2 regwptr[18]
|
|
+#define ureg_o3 regwptr[19]
|
|
+#define ureg_o4 regwptr[20]
|
|
+#define ureg_o5 regwptr[21]
|
|
+#define ureg_o6 regwptr[22]
|
|
+#define ureg_o7 regwptr[23]
|
|
+#define ureg_fp ureg_i6
|
|
+#define ureg_sp ureg_o6
|
|
+#define ureg_tnpc ureg_i0
|
|
+#define ureg_tpc ureg_i1
|
|
+
|
|
+#define TARGET_FPRS_FEF (1 << 2)
|
|
+#define TARGET_MC_VERSION 1L
|
|
+
|
|
+/* compare to sparc64/sparc64/machdep.c set_mcontext() */
|
|
+static inline int
|
|
+restore_sigmcontext(CPUSPARCState *regs, target_mcontext_t *mc)
|
|
+{
|
|
+ int err = 0;
|
|
+
|
|
+ err |= __get_user(regs->gregs[1], &mc->mc_global[1]);
|
|
+ err |= __get_user(regs->gregs[2], &mc->mc_global[2]);
|
|
+ err |= __get_user(regs->gregs[3], &mc->mc_global[3]);
|
|
+ err |= __get_user(regs->gregs[4], &mc->mc_global[4]);
|
|
+ err |= __get_user(regs->gregs[5], &mc->mc_global[5]);
|
|
+ err |= __get_user(regs->gregs[6], &mc->mc_global[6]);
|
|
+
|
|
+ err |= __get_user(regs->ureg_o0, &mc->mc_out[0]);
|
|
+ err |= __get_user(regs->ureg_o1, &mc->mc_out[1]);
|
|
+ err |= __get_user(regs->ureg_o2, &mc->mc_out[2]);
|
|
+ err |= __get_user(regs->ureg_o3, &mc->mc_out[3]);
|
|
+ err |= __get_user(regs->ureg_o4, &mc->mc_out[4]);
|
|
+ err |= __get_user(regs->ureg_o5, &mc->mc_out[5]);
|
|
+ err |= __get_user(regs->ureg_o6, &mc->mc_out[6]);
|
|
+ err |= __get_user(regs->ureg_o7, &mc->mc_out[0]);
|
|
+
|
|
+ err |= __get_user(regs->ureg_l0, &mc->mc_fprs); /* mc_local[0] */
|
|
+ err |= __get_user(regs->ureg_l1, &mc->mc_fsr); /* mc_local[1] */
|
|
+ err |= __get_user(regs->ureg_l2, &mc->mc_qsr); /* mc_local[2] */
|
|
+
|
|
+ err |= __get_user(regs->ureg_i0, &mc->mc_tnpc); /* mc_in[0] */
|
|
+ err |= __get_user(regs->ureg_i1, &mc->mc_tpc); /* mc_in[1] */
|
|
+ err |= __get_user(regs->ureg_i2, &mc->mc_tstate);/* mc_in[2] */
|
|
+
|
|
+ err |= __get_user(regs->ureg_i4, &mc->mc_y); /* mc_in[4] */
|
|
+
|
|
+ /* XXX
|
|
+ if ((regs->ureg_l0 & TARGET_FPRS_FEF) != 0) {
|
|
+ regs->ureg_l0 = 0;
|
|
+ for(i = 0; i < 64; i++)
|
|
+ err |= __get_user(regs->fpr[i], &mc->mc_fp[i]);
|
|
+ }
|
|
+ */
|
|
+
|
|
+ return (err);
|
|
+}
|
|
+
|
|
+/* compare to sparc64/sparc64/machdep.c get_mcontext() */
|
|
+static inline int
|
|
+setup_sigmcontext(CPUSPARCState *regs, target_mcontext_t *mc)
|
|
+{
|
|
+ int err = 0;
|
|
+ abi_ulong ver = TARGET_MC_VERSION;
|
|
+
|
|
+ err |= __put_user(ver, &mc->mc_flags); /* aka. mc_global[0] */
|
|
+ err |= __put_user(regs->gregs[1], &mc->mc_global[1]);
|
|
+ err |= __put_user(regs->gregs[2], &mc->mc_global[2]);
|
|
+ err |= __put_user(regs->gregs[3], &mc->mc_global[3]);
|
|
+ err |= __put_user(regs->gregs[4], &mc->mc_global[4]);
|
|
+ err |= __put_user(regs->gregs[5], &mc->mc_global[5]);
|
|
+ err |= __put_user(regs->gregs[6], &mc->mc_global[6]);
|
|
+ /* skip %g7 since it is used as the userland TLS register */
|
|
+
|
|
+ err |= __put_user(regs->ureg_o0, &mc->mc_out[0]);
|
|
+ err |= __put_user(regs->ureg_o1, &mc->mc_out[1]);
|
|
+ err |= __put_user(regs->ureg_o2, &mc->mc_out[2]);
|
|
+ err |= __put_user(regs->ureg_o3, &mc->mc_out[3]);
|
|
+ err |= __put_user(regs->ureg_o4, &mc->mc_out[4]);
|
|
+ err |= __put_user(regs->ureg_o5, &mc->mc_out[5]);
|
|
+ err |= __put_user(regs->ureg_o6, &mc->mc_out[6]);
|
|
+ err |= __put_user(regs->ureg_o7, &mc->mc_out[7]);
|
|
+
|
|
+ err |= __put_user(regs->ureg_l0, &mc->mc_fprs); /* mc_local[0] */
|
|
+ err |= __put_user(regs->ureg_l1, &mc->mc_fsr); /* mc_local[1] */
|
|
+ err |= __put_user(regs->ureg_l2, &mc->mc_qsr); /* mc_local[2] */
|
|
+
|
|
+ err |= __put_user(regs->ureg_i0, &mc->mc_tnpc); /* mc_in[0] */
|
|
+ err |= __put_user(regs->ureg_i1, &mc->mc_tpc); /* mc_in[1] */
|
|
+ err |= __put_user(regs->ureg_i2, &mc->mc_tstate);/* mc_in[2] */
|
|
+
|
|
+ err |= __put_user(regs->ureg_i4, &mc->mc_y); /* mc_in[4] */
|
|
+
|
|
+ /* XXX
|
|
+ if ((regs->ureg_l0 & TARGET_FPRS_FEF) != 0) {
|
|
+ for(i = 0; i < 64; i++)
|
|
+ err |= __put_user(regs->fpr[i], &mc->mc_fp[i]);
|
|
+ }
|
|
+ */
|
|
+
|
|
+ return (err);
|
|
+}
|
|
+
|
|
+static inline abi_ulong
|
|
+get_sigframe(struct target_sigaction *ka, CPUSPARCState *regs, size_t frame_size)
|
|
+{
|
|
+ abi_ulong sp;
|
|
+
|
|
+ /* Use default user stack */
|
|
+ sp = regs->ureg_sp;
|
|
+
|
|
+ if ((ka->sa_flags & TARGET_SA_ONSTACK) && (sas_ss_flags(sp) == 0)) {
|
|
+ sp = target_sigaltstack_used.ss_sp + target_sigaltstack_used.ss_size;
|
|
+ }
|
|
+
|
|
+ return (sp - frame_size);
|
|
+}
|
|
+
|
|
+/* compare to sparc64/sparc64/machdep.c sendsig() */
|
|
+static void setup_frame(int sig, struct target_sigaction *ka,
|
|
+ target_sigset_t *set, CPUSPARCState *regs)
|
|
+{
|
|
+ struct target_sigframe *frame;
|
|
+ abi_ulong frame_addr;
|
|
+ int i;
|
|
+
|
|
+ if (!sparc_user_sigtramp) {
|
|
+ /* No signal trampoline... kill the process. */
|
|
+ fprintf(stderr, "setup_frame(): no sigtramp\n");
|
|
+ force_sig(TARGET_SIGKILL);
|
|
+ }
|
|
+
|
|
+ frame_addr = get_sigframe(ka, regs, sizeof(*frame));
|
|
+ if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0))
|
|
+ goto give_sigsegv;
|
|
+
|
|
+ if (setup_sigmcontext(regs, &frame->sf_uc.uc_mcontext))
|
|
+ goto give_sigsegv;
|
|
+
|
|
+ for(i = 0; i < TARGET_NSIG_WORDS; i++) {
|
|
+ if (__put_user(set->__bits[i], &frame->sf_uc.uc_sigmask.__bits[i]))
|
|
+ goto give_sigsegv;
|
|
+ }
|
|
+
|
|
+ /* Fill in siginfo structure */
|
|
+ if (__put_user(sig, &frame->sf_si.si_signo))
|
|
+ goto give_sigsegv;
|
|
+ if (__put_user(TARGET_SA_SIGINFO, &frame->sf_si.si_code))
|
|
+ goto give_sigsegv;
|
|
+
|
|
+ /* Arguments to signal handler:
|
|
+ *
|
|
+ * o0 = signal number
|
|
+ * o1 = pointer to siginfo struct
|
|
+ * o2 = pointer to ucontext struct
|
|
+ * o3 = (not used in new style)
|
|
+ * o4 = signal handler address (called by sigtramp)
|
|
+ */
|
|
+ regs->ureg_o0 = sig;
|
|
+ regs->ureg_o1 = frame_addr +
|
|
+ offsetof(struct target_sigframe, sf_si);
|
|
+ regs->ureg_o2 = frame_addr +
|
|
+ offsetof(struct target_sigframe, sf_uc);
|
|
+ /* env->ureg_o3 used in the Old FreeBSD-style arguments. */
|
|
+ regs->ureg_o4 = ka->_sa_handler;
|
|
+
|
|
+ regs->ureg_tpc = sparc_user_sigtramp;
|
|
+ regs->ureg_tnpc = (regs->ureg_tpc + 4);
|
|
+ regs->ureg_sp = frame_addr - 2047 /* SPOFF */;
|
|
+ unlock_user_struct(frame, frame_addr, 1);
|
|
+ return;
|
|
+
|
|
+give_sigsegv:
|
|
+ unlock_user_struct(frame, frame_addr, 1);
|
|
+ force_sig(TARGET_SIGSEGV);
|
|
+}
|
|
+
|
|
+
|
|
+long do_sigreturn(CPUSPARCState *regs, abi_ulong uc_addr)
|
|
+{
|
|
+ target_ucontext_t *ucontext;
|
|
+ sigset_t blocked;
|
|
+ target_sigset_t target_set;
|
|
+ int i;
|
|
+
|
|
+#if defined(DEBUG_SIGNAL)
|
|
+ fprintf(stderr, "do_sigreturn\n");
|
|
+#endif
|
|
+ if (!lock_user_struct(VERIFY_READ, ucontext, uc_addr, 1))
|
|
+ goto badframe;
|
|
+
|
|
+ for(i = 0; i < TARGET_NSIG_WORDS; i++) {
|
|
+ if (__get_user(target_set.__bits[i], &ucontext->uc_sigmask.__bits[i]))
|
|
+ goto badframe;
|
|
+ }
|
|
+
|
|
+ if (restore_sigmcontext(regs, &ucontext->uc_mcontext))
|
|
+ goto badframe;
|
|
+
|
|
+ target_to_host_sigset_internal(&blocked, &target_set);
|
|
+ sigprocmask(SIG_SETMASK, &blocked, NULL);
|
|
+
|
|
+ return (-TARGET_QEMU_ESIGRETURN);
|
|
+
|
|
+badframe:
|
|
+ force_sig(TARGET_SIGSEGV);
|
|
+ return (0);
|
|
+}
|
|
+
|
|
+#else
|
|
+
|
|
+static void
|
|
+setup_frame(int sig, struct target_sigaction *ka, target_sigset_t *set,
|
|
+ CPUArchState *env)
|
|
+{
|
|
+ fprintf(stderr, "setup_frame: not implemented\n");
|
|
+}
|
|
+
|
|
+#if 0
|
|
+static void
|
|
+setup_rt_frame(int sig, struct target_sigaction *ka, target_siginfo_t *info,
|
|
+ target_sigset_t *set, CPUArchState *env)
|
|
+{
|
|
+ fprintf(stderr, "setup_rt_frame: not implemented\n");
|
|
+}
|
|
+#endif
|
|
+
|
|
+long
|
|
+do_sigreturn(CPUArchState *env, abi_ulong uc_addr)
|
|
+{
|
|
+ fprintf(stderr,"do_sigreturn: not implemented\n");
|
|
+ return (-TARGET_ENOSYS);
|
|
+}
|
|
+
|
|
+long
|
|
+do_rt_sigreturn(CPUArchState *env)
|
|
+{
|
|
+ fprintf(stderr, "do_rt_sigreturn: not implemented\n");
|
|
+ return (-TARGET_ENOSYS);
|
|
+}
|
|
+#endif
|
|
+
|
|
+void
|
|
+signal_init(void)
|
|
+{
|
|
+ struct sigaction act;
|
|
+ struct sigaction oact;
|
|
+ int i, j;
|
|
+ int host_sig;
|
|
+
|
|
+ /* Generate the signal conversion tables. */
|
|
+ for(i = 1; i < _NSIG; i++) {
|
|
+ if (host_to_target_signal_table[i] == 0)
|
|
+ host_to_target_signal_table[i] = i;
|
|
+ }
|
|
+ for(i = 1; i < _NSIG; i++) {
|
|
+ j = host_to_target_signal_table[i];
|
|
+ target_to_host_signal_table[j] = i;
|
|
+ }
|
|
+
|
|
+ /*
|
|
+ * Set all host signal handlers. ALL signals are blocked during the
|
|
+ * handlers to serialize them.
|
|
+ */
|
|
+ memset(sigact_table, 0, sizeof(sigact_table));
|
|
+
|
|
+ sigfillset(&act.sa_mask);
|
|
+ act.sa_sigaction = host_signal_handler;
|
|
+
|
|
+ for (i = 1; i <= TARGET_NSIG; i++) {
|
|
+ host_sig = target_to_host_signal(i);
|
|
+ sigaction(host_sig, NULL, &oact);
|
|
+ if (oact.sa_sigaction == (void *)SIG_IGN) {
|
|
+ sigact_table[i - 1]._sa_handler = TARGET_SIG_IGN;
|
|
+ } else if (oact.sa_sigaction == (void *)SIG_DFL) {
|
|
+ sigact_table[i - 1]._sa_handler = TARGET_SIG_DFL;
|
|
+ }
|
|
+ /*
|
|
+ * If there's already a handler installed then something has
|
|
+ * gone horribly wrong, so don't even try to handle that case.
|
|
+ * Install some handlers for our own use. We need at least
|
|
+ * SIGSEGV and SIGBUS, to detect exceptions. We can not just
|
|
+ * trap all signals because it affects syscall interrupt
|
|
+ * behavior. But do trap all default-fatal signals.
|
|
+ */
|
|
+ if (fatal_signal(i)) {
|
|
+ sigaction(host_sig, &act, NULL);
|
|
+ }
|
|
+ }
|
|
+}
|
|
+
|
|
+void
|
|
+process_pending_signals(CPUArchState *cpu_env)
|
|
+{
|
|
+ int sig;
|
|
+ abi_ulong handler;
|
|
+ sigset_t set, old_set;
|
|
+ target_sigset_t target_old_set;
|
|
+ struct emulated_sigtable *k;
|
|
+ struct target_sigaction *sa;
|
|
+ struct sigqueue *q;
|
|
+ TaskState *ts = cpu_env->opaque;
|
|
+
|
|
+ if (!ts->signal_pending)
|
|
+ return;
|
|
+
|
|
+ /* FIXME: This is not threadsafe. */
|
|
+ k = ts->sigtab;
|
|
+ for(sig = 1; sig <= TARGET_NSIG; sig++) {
|
|
+ if (k->pending)
|
|
+ goto handle_signal;
|
|
+ k++;
|
|
+ }
|
|
+#ifdef DEBUG_SIGNAL
|
|
+ fprintf(stderr, "qemu: process_pending_signals has no signals\n");
|
|
+#endif
|
|
+ /* If no signal is pending then just return. */
|
|
+ ts->signal_pending = 0;
|
|
+ return;
|
|
+
|
|
+handle_signal:
|
|
+#ifdef DEBUG_SIGNAL
|
|
+ fprintf(stderr, "qemu: process signal %d\n", sig);
|
|
+#endif
|
|
+
|
|
+ /* Dequeue signal. */
|
|
+ q = k->first;
|
|
+ k->first = q->next;
|
|
+ if (!k->first)
|
|
+ k->pending = 0;
|
|
+
|
|
+ sig = gdb_handlesig (cpu_env, sig);
|
|
+ if (!sig) {
|
|
+ sa = NULL;
|
|
+ handler = TARGET_SIG_IGN;
|
|
+ } else {
|
|
+ sa = &sigact_table[sig - 1];
|
|
+ handler = sa->_sa_handler;
|
|
+ }
|
|
+
|
|
+ if (handler == TARGET_SIG_DFL) {
|
|
+#ifdef DEBUG_SIGNAL
|
|
+ fprintf(stderr, "qemu: TARGET_SIG_DFL\n");
|
|
+#endif
|
|
+ /*
|
|
+ * default handler : ignore some signal. The other are job
|
|
+ * control or fatal.
|
|
+ */
|
|
+ if (TARGET_SIGTSTP == sig || TARGET_SIGTTIN == sig ||
|
|
+ TARGET_SIGTTOU == sig) {
|
|
+ kill(getpid(),SIGSTOP);
|
|
+ } else if (TARGET_SIGCHLD != sig && TARGET_SIGURG != sig &&
|
|
+ TARGET_SIGWINCH != sig && TARGET_SIGCONT != sig) {
|
|
+ force_sig(sig);
|
|
+ }
|
|
+ } else if (TARGET_SIG_IGN == handler) {
|
|
+ /* ignore sig */
|
|
+#ifdef DEBUG_SIGNAL
|
|
+ fprintf(stderr, "qemu: TARGET_SIG_IGN\n");
|
|
+#endif
|
|
+ } else if (TARGET_SIG_ERR == handler) {
|
|
+#ifdef DEBUG_SIGNAL
|
|
+ fprintf(stderr, "qemu: TARGET_SIG_ERR\n");
|
|
+#endif
|
|
+ force_sig(sig);
|
|
+ } else {
|
|
+ /* compute the blocked signals during the handler execution */
|
|
+ target_to_host_sigset(&set, &sa->sa_mask);
|
|
+ /*
|
|
+ * SA_NODEFER indicates that the current signal should not be
|
|
+ * blocked during the handler.
|
|
+ */
|
|
+ if (!(sa->sa_flags & TARGET_SA_NODEFER))
|
|
+ sigaddset(&set, target_to_host_signal(sig));
|
|
+
|
|
+ /* block signals in the handler */
|
|
+ sigprocmask(SIG_BLOCK, &set, &old_set);
|
|
+
|
|
+ /*
|
|
+ * Save the previous blocked signal state to restore it at the
|
|
+ * end of the signal execution (see do_sigreturn).
|
|
+ */
|
|
+ host_to_target_sigset_internal(&target_old_set, &old_set);
|
|
+
|
|
+#if 0
|
|
+#if defined(TARGET_I386) && !defined(TARGET_X86_64)
|
|
+ /* if the CPU is in VM86 mode, we restore the 32 bit values */
|
|
+ {
|
|
+ CPUX86State *env = cpu_env;
|
|
+ if (env->eflags & VM_MASK)
|
|
+ save_v86_state(env);
|
|
+ }
|
|
+#endif
|
|
+#endif
|
|
+ /* prepare the stack frame of the virtual CPU */
|
|
+#if 0 /* XXX no rt for fbsd */
|
|
+ if (sa->sa_flags & TARGET_SA_SIGINFO)
|
|
+ setup_rt_frame(sig, sa, &q->info, &target_old_set,
|
|
+ cpu_env);
|
|
+ else
|
|
+#endif
|
|
+ setup_frame(sig, sa, &target_old_set, cpu_env);
|
|
+ if (sa->sa_flags & TARGET_SA_RESETHAND)
|
|
+ sa->_sa_handler = TARGET_SIG_DFL;
|
|
+ }
|
|
+ if (q != &k->info)
|
|
+ free_sigqueue(cpu_env, q);
|
|
}
|
|
diff --git a/bsd-user/socket.h b/bsd-user/socket.h
|
|
new file mode 100644
|
|
index 0000000..c9e019b
|
|
--- /dev/null
|
|
+++ b/bsd-user/socket.h
|
|
@@ -0,0 +1,66 @@
|
|
+/*
|
|
+ * Target socket definitions.
|
|
+ */
|
|
+
|
|
+/*
|
|
+ * Types
|
|
+ */
|
|
+#define TARGET_SOCK_STREAM 1 /* stream socket */
|
|
+#define TARGET_SOCK_DGRAM 2 /* datagram socket */
|
|
+#define TARGET_SOCK_RAW 3 /* raw-protocol interface */
|
|
+#define TARGET_SOCK_RDM 4 /* reliably-delivered message */
|
|
+#define TARGET_SOCK_SEQPACKET 5 /* sequenced packet stream */
|
|
+
|
|
+
|
|
+/*
|
|
+ * Option flags per-socket.
|
|
+ */
|
|
+
|
|
+#define TARGET_SO_DEBUG 0x0001 /* turn on debugging info recording */
|
|
+#define TARGET_SO_ACCEPTCONN 0x0002 /* socket has had listen() */
|
|
+#define TARGET_SO_REUSEADDR 0x0004 /* allow local address reuse */
|
|
+#define TARGET_SO_KEEPALIVE 0x0008 /* keep connections alive */
|
|
+#define TARGET_SO_DONTROUTE 0x0010 /* just use interface addresses */
|
|
+#define TARGET_SO_BROADCAST 0x0020 /* permit sending of broadcast msgs */
|
|
+#define TARGET_SO_USELOOPBACK 0x0040 /* bypass hardware when possible */
|
|
+#define TARGET_SO_LINGER 0x0080 /* linger on close if data present */
|
|
+#define TARGET_SO_OOBINLINE 0x0100 /* leave received OOB data in line */
|
|
+#define TARGET_SO_REUSEPORT 0x0200 /* allow local address & port reuse */
|
|
+#define TARGET_SO_TIMESTAMP 0x0400 /* timestamp received dgram traffic */
|
|
+#define TARGET_SO_NOSIGPIPE 0x0800 /* no SIGPIPE from EPIPE */
|
|
+#define TARGET_SO_ACCEPTFILTER 0x1000 /* there is an accept filter */
|
|
+#define TARGET_SO_BINTIME 0x2000 /* timestamp received dgram traffic */
|
|
+#define TARGET_SO_NO_OFFLOAD 0x4000 /* socket cannot be offloaded */
|
|
+#define TARGET_SO_NO_DDP 0x8000 /* disable direct data placement */
|
|
+
|
|
+/*
|
|
+ * Additional options, not kept in so_options.
|
|
+ */
|
|
+#define TARGET_SO_SNDBUF 0x1001 /* send buffer size */
|
|
+#define TARGET_SO_RCVBUF 0x1002 /* receive buffer size */
|
|
+#define TARGET_SO_SNDLOWAT 0x1003 /* send low-water mark */
|
|
+#define TARGET_SO_RCVLOWAT 0x1004 /* receive low-water mark */
|
|
+#define TARGET_SO_SNDTIMEO 0x1005 /* send timeout */
|
|
+#define TARGET_SO_RCVTIMEO 0x1006 /* receive timeout */
|
|
+#define TARGET_SO_ERROR 0x1007 /* get error status and clear */
|
|
+#define TARGET_SO_TYPE 0x1008 /* get socket type */
|
|
+#define TARGET_SO_LABEL 0x1009 /* socket's MAC label */
|
|
+#define TARGET_SO_PEERLABEL 0x1010 /* socket's peer's MAC label */
|
|
+#define TARGET_SO_LISTENQLIMIT 0x1011 /* socket's backlog limit */
|
|
+#define TARGET_SO_LISTENQLEN 0x1012 /* socket's complete queue length */
|
|
+#define TARGET_SO_LISTENINCQLEN 0x1013 /* socket's incomplete queue length */
|
|
+#define TARGET_SO_SETFIB 0x1014 /* use this FIB to route */
|
|
+#define TARGET_SO_USER_COOKIE 0x1015 /* user cookie (dummynet etc.) */
|
|
+#define TARGET_SO_PROTOCOL 0x1016 /* get socket protocol (Linux name) */
|
|
+
|
|
+/* alias for SO_PROTOCOL (SunOS name) */
|
|
+#define TARGET_SO_PROTOTYPE TARGET_SO_PROTOCOL
|
|
+
|
|
+/*
|
|
+ * Level number for (get/set)sockopt() to apply to socket itself.
|
|
+ */
|
|
+#define TARGET_SOL_SOCKET 0xffff /* options for socket level */
|
|
+
|
|
+#ifndef CMSG_ALIGN
|
|
+#define CMSG_ALIGN(len) ( ((len)+sizeof(long)-1) & ~(sizeof(long)-1) )
|
|
+#endif
|
|
diff --git a/bsd-user/sparc/target_signal.h b/bsd-user/sparc/target_signal.h
|
|
index 5b2abba..79dfc1e 100644
|
|
--- a/bsd-user/sparc/target_signal.h
|
|
+++ b/bsd-user/sparc/target_signal.h
|
|
@@ -3,15 +3,6 @@
|
|
|
|
#include "cpu.h"
|
|
|
|
-/* this struct defines a stack used during syscall handling */
|
|
-
|
|
-typedef struct target_sigaltstack {
|
|
- abi_ulong ss_sp;
|
|
- abi_long ss_flags;
|
|
- abi_ulong ss_size;
|
|
-} target_stack_t;
|
|
-
|
|
-
|
|
#ifndef UREG_I6
|
|
#define UREG_I6 6
|
|
#endif
|
|
@@ -19,6 +10,9 @@ typedef struct target_sigaltstack {
|
|
#define UREG_FP UREG_I6
|
|
#endif
|
|
|
|
+#define TARGET_MINSIGSTKSZ (512 * 4)
|
|
+#define TARGET_SIGSTKSZ (TARGET_MINSIGSTKSZ + 32768)
|
|
+
|
|
static inline abi_ulong get_sp_from_cpustate(CPUSPARCState *state)
|
|
{
|
|
return state->regwptr[UREG_FP];
|
|
diff --git a/bsd-user/sparc/target_vmparam.h b/bsd-user/sparc/target_vmparam.h
|
|
new file mode 100644
|
|
index 0000000..9494c46
|
|
--- /dev/null
|
|
+++ b/bsd-user/sparc/target_vmparam.h
|
|
@@ -0,0 +1,23 @@
|
|
+#ifndef _TARGET_VMPARAM_H_
|
|
+#define _TARGET_VMPARAM_H_
|
|
+
|
|
+#define TARGET_USRSTACK 0
|
|
+
|
|
+#ifdef __FreeBSD__
|
|
+struct target_ps_strings {
|
|
+ abi_ulong ps_argvstr;
|
|
+ uint32_t ps_nargvstr;
|
|
+ abi_ulong ps_envstr;
|
|
+ uint32_t ps_nenvstr;
|
|
+};
|
|
+
|
|
+#define TARGET_SPACE_USRSPACE 4096
|
|
+#define TARGET_ARG_MAX 262144
|
|
+
|
|
+#define TARGET_PS_STRINGS (TARGET_USRSTACK - sizeof(struct target_ps_strings))
|
|
+
|
|
+#define TARGET_SZSIGCODE 0
|
|
+#endif /* __FreeBSD__ */
|
|
+
|
|
+#endif /* _TARGET_VMPARAM_H_ */
|
|
+
|
|
diff --git a/bsd-user/sparc64/target_signal.h b/bsd-user/sparc64/target_signal.h
|
|
index 5b2abba..d3e58bb 100644
|
|
--- a/bsd-user/sparc64/target_signal.h
|
|
+++ b/bsd-user/sparc64/target_signal.h
|
|
@@ -3,15 +3,6 @@
|
|
|
|
#include "cpu.h"
|
|
|
|
-/* this struct defines a stack used during syscall handling */
|
|
-
|
|
-typedef struct target_sigaltstack {
|
|
- abi_ulong ss_sp;
|
|
- abi_long ss_flags;
|
|
- abi_ulong ss_size;
|
|
-} target_stack_t;
|
|
-
|
|
-
|
|
#ifndef UREG_I6
|
|
#define UREG_I6 6
|
|
#endif
|
|
@@ -19,6 +10,9 @@ typedef struct target_sigaltstack {
|
|
#define UREG_FP UREG_I6
|
|
#endif
|
|
|
|
+#define TARGET_MINSIGSTKSZ (1024 * 4)
|
|
+#define TARGET_SIGSTKSZ (TARGET_MINSIGSTKSZ + 32768)
|
|
+
|
|
static inline abi_ulong get_sp_from_cpustate(CPUSPARCState *state)
|
|
{
|
|
return state->regwptr[UREG_FP];
|
|
diff --git a/bsd-user/sparc64/target_vmparam.h b/bsd-user/sparc64/target_vmparam.h
|
|
new file mode 100644
|
|
index 0000000..12af063
|
|
--- /dev/null
|
|
+++ b/bsd-user/sparc64/target_vmparam.h
|
|
@@ -0,0 +1,30 @@
|
|
+#ifndef _TARGET_VMPARAM_H_
|
|
+#define _TARGET_VMPARAM_H_
|
|
+
|
|
+#if defined(__FreeBSD__)
|
|
+#define TARGET_VM_MINUSER_ADDRESS (0x0000000000000000UL)
|
|
+#define TARGET_VM_MAXUSER_ADDRESS (0x000007fe00000000UL)
|
|
+
|
|
+#define TARGET_USRSTACK TARGET_VM_MAXUSER_ADDRESS
|
|
+
|
|
+struct target_ps_strings {
|
|
+ abi_ulong ps_argvstr;
|
|
+ uint32_t ps_nargvstr;
|
|
+ abi_ulong ps_envstr;
|
|
+ uint32_t ps_nenvstr;
|
|
+};
|
|
+
|
|
+#define TARGET_SPACE_USRSPACE 4096
|
|
+#define TARGET_ARG_MAX 262144
|
|
+
|
|
+#define TARGET_PS_STRINGS (TARGET_USRSTACK - sizeof(struct target_ps_strings))
|
|
+
|
|
+#define TARGET_SZSIGCODE 0
|
|
+
|
|
+#else
|
|
+
|
|
+#define TARGET_USRSTACK 0
|
|
+#endif
|
|
+
|
|
+#endif /* _TARGET_VMPARAM_H_ */
|
|
+
|
|
diff --git a/bsd-user/syscall.c b/bsd-user/syscall.c
|
|
index 443b01a..c627c62 100644
|
|
--- a/bsd-user/syscall.c
|
|
+++ b/bsd-user/syscall.c
|
|
@@ -2,6 +2,7 @@
|
|
* BSD syscalls
|
|
*
|
|
* Copyright (c) 2003 - 2008 Fabrice Bellard
|
|
+ * Copyright (c) 2012 Stacey Son <sson@FreeBSD.org>
|
|
*
|
|
* 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
|
|
@@ -21,18 +22,37 @@
|
|
#include <stdint.h>
|
|
#include <stdarg.h>
|
|
#include <string.h>
|
|
+#include <dirent.h>
|
|
#include <errno.h>
|
|
#include <unistd.h>
|
|
#include <fcntl.h>
|
|
#include <time.h>
|
|
#include <limits.h>
|
|
+#include <poll.h>
|
|
#include <sys/types.h>
|
|
+#include <sys/time.h>
|
|
#include <sys/mman.h>
|
|
#include <sys/syscall.h>
|
|
#include <sys/param.h>
|
|
+#include <sys/resource.h>
|
|
#include <sys/sysctl.h>
|
|
+#include <sys/event.h>
|
|
+#include <sys/mount.h>
|
|
+#include <sys/wait.h>
|
|
+#include <sys/socket.h>
|
|
+#ifdef __FreeBSD__
|
|
+#include <sys/regression.h>
|
|
+#include <sys/procdesc.h>
|
|
+#endif
|
|
+#include <sys/un.h>
|
|
+#include <sys/ipc.h>
|
|
+#include <sys/sem.h>
|
|
+#include <sys/shm.h>
|
|
+#include <sys/msg.h>
|
|
#include <utime.h>
|
|
|
|
+#include <netinet/in.h>
|
|
+
|
|
#include "qemu.h"
|
|
#include "qemu-common.h"
|
|
|
|
@@ -50,6 +70,13 @@ static inline abi_long get_errno(abi_long ret)
|
|
return ret;
|
|
}
|
|
|
|
+static inline int
|
|
+host_to_target_errno(int err)
|
|
+{
|
|
+ /* XXX need to translate host errnos here */
|
|
+ return (err);
|
|
+}
|
|
+
|
|
#define target_to_host_bitmask(x, tbl) (x)
|
|
|
|
static inline int is_error(abi_long ret)
|
|
@@ -152,13 +179,65 @@ static abi_long do_freebsd_sysarch(CPUX86State *env, int op, abi_ulong parms)
|
|
#endif
|
|
|
|
#ifdef TARGET_SPARC
|
|
+struct target_sparc_sigtramp_install_args {
|
|
+ abi_ulong sia_new; /* address of sigtramp code */
|
|
+ abi_ulong sia_old; /* user address to store old sigtramp addr */
|
|
+};
|
|
+
|
|
+abi_ulong sparc_user_sigtramp = 0;
|
|
+
|
|
static abi_long do_freebsd_sysarch(void *env, int op, abi_ulong parms)
|
|
{
|
|
- /* XXX handle
|
|
- * TARGET_FREEBSD_SPARC_UTRAP_INSTALL,
|
|
- * TARGET_FREEBSD_SPARC_SIGTRAMP_INSTALL
|
|
- */
|
|
- return -TARGET_EINVAL;
|
|
+ int ret = 0;
|
|
+ abi_ulong val, old;
|
|
+ /*
|
|
+ struct target_sparc_sigtramp_install_args *target_sigtramp_args;
|
|
+ */
|
|
+
|
|
+
|
|
+ switch(op) {
|
|
+ case TARGET_SPARC_SIGTRAMP_INSTALL:
|
|
+ {
|
|
+
|
|
+#if 0
|
|
+ /* Sparc userland is giving us a new sigtramp code ptr. */
|
|
+ if (!(target_sigtramp_args = lock_user(VERIFY_WRITE, parms,
|
|
+ sizeof(*target_sigtramp_args), 1))) {
|
|
+ ret = -TARGET_EFAULT;
|
|
+ } else {
|
|
+ if (target_sigtramp_args->sia_old) {
|
|
+ put_user_ual(sparc_user_sigtramp,
|
|
+ target_sigtramp_args->sia_old);
|
|
+ }
|
|
+ sparc_user_sigtramp = target_sigtramp_args->sia_new;
|
|
+ unlock_user(target_sigtramp_args, parms, 0);
|
|
+
|
|
+ }
|
|
+#endif
|
|
+ val = sparc_user_sigtramp;
|
|
+ if (get_user(sparc_user_sigtramp, parms, abi_ulong)) {
|
|
+ return (-TARGET_EFAULT);
|
|
+ }
|
|
+ parms += sizeof(abi_ulong);
|
|
+ if (get_user(old, parms, abi_ulong)) {
|
|
+ return (-TARGET_EFAULT);
|
|
+ }
|
|
+ if (old) {
|
|
+ if (put_user(val, old, abi_ulong)) {
|
|
+ return (-TARGET_EFAULT);
|
|
+ }
|
|
+ }
|
|
+ }
|
|
+ break;
|
|
+
|
|
+ case TARGET_SPARC_UTRAP_INSTALL:
|
|
+ /* XXX not currently handled */
|
|
+ default:
|
|
+ ret = -TARGET_EINVAL;
|
|
+ break;
|
|
+ }
|
|
+
|
|
+ return (ret);
|
|
}
|
|
#endif
|
|
|
|
@@ -168,7 +247,17 @@ static abi_long do_freebsd_sysarch(void *env, int op, abi_ulong parms)
|
|
return -TARGET_EINVAL;
|
|
}
|
|
#endif
|
|
+
|
|
+#ifdef TARGET_MIPS
|
|
+static abi_long do_freebsd_sysarch(void *env, int op, abi_ulong parms)
|
|
+{
|
|
+ return -TARGET_EINVAL;
|
|
+}
|
|
+#endif
|
|
+
|
|
#ifdef __FreeBSD__
|
|
+extern int _getlogin(char *, int);
|
|
+
|
|
/*
|
|
* XXX this uses the undocumented oidfmt interface to find the kind of
|
|
* a requested sysctl, see /sys/kern/kern_sysctl.c:sysctl_sysctl_oidfmt()
|
|
@@ -327,92 +416,3799 @@ static abi_long unlock_iovec(struct iovec *vec, abi_ulong target_addr,
|
|
return 0;
|
|
}
|
|
|
|
-/* do_syscall() should always have a single exit point at the end so
|
|
- that actions, such as logging of syscall results, can be performed.
|
|
- All errnos that do_syscall() returns must be -TARGET_<errcode>. */
|
|
-abi_long do_freebsd_syscall(void *cpu_env, int num, abi_long arg1,
|
|
- abi_long arg2, abi_long arg3, abi_long arg4,
|
|
- abi_long arg5, abi_long arg6, abi_long arg7,
|
|
- abi_long arg8)
|
|
+static inline abi_long
|
|
+target_to_host_sockaddr(struct sockaddr *addr, abi_ulong target_addr,
|
|
+ socklen_t len)
|
|
{
|
|
- abi_long ret;
|
|
- void *p;
|
|
+ const socklen_t unix_maxlen = sizeof (struct sockaddr_un);
|
|
+ sa_family_t sa_family;
|
|
+ struct target_sockaddr *target_saddr;
|
|
|
|
-#ifdef DEBUG
|
|
- gemu_log("freebsd syscall %d\n", num);
|
|
-#endif
|
|
- if(do_strace)
|
|
- print_freebsd_syscall(num, arg1, arg2, arg3, arg4, arg5, arg6);
|
|
+ target_saddr = lock_user(VERIFY_READ, target_addr, len, 1);
|
|
+ if (!target_saddr)
|
|
+ return -TARGET_EFAULT;
|
|
|
|
- switch(num) {
|
|
- case TARGET_FREEBSD_NR_exit:
|
|
-#ifdef TARGET_GPROF
|
|
- _mcleanup();
|
|
+ sa_family = tswap16(target_saddr->sa_family);
|
|
+
|
|
+ /*
|
|
+ * Oops. The caller might send a incomplete sun_path; sun_path
|
|
+ * must be terminated by \0 (see the manual page), but unfortunately
|
|
+ * it is quite common to specify sockaddr_un length as
|
|
+ * "strlen(x->sun_path)" while it should be "strlen(...) + 1". We will
|
|
+ * fix that here if needed.
|
|
+ */
|
|
+ if (sa_family == AF_UNIX) {
|
|
+ if (len < unix_maxlen && len > 0) {
|
|
+ char *cp = (char*)target_saddr;
|
|
+
|
|
+ if ( cp[len-1] && !cp[len] )
|
|
+ len++;
|
|
+ }
|
|
+ if (len > unix_maxlen)
|
|
+ len = unix_maxlen;
|
|
+ }
|
|
+
|
|
+ memcpy(addr, target_saddr, len);
|
|
+ addr->sa_family = sa_family;
|
|
+ unlock_user(target_saddr, target_addr, 0);
|
|
+
|
|
+ return (0);
|
|
+}
|
|
+
|
|
+static inline abi_long
|
|
+host_to_target_sockaddr(abi_ulong target_addr, struct sockaddr *addr,
|
|
+ socklen_t len)
|
|
+{
|
|
+ struct target_sockaddr *target_saddr;
|
|
+
|
|
+ target_saddr = lock_user(VERIFY_WRITE, target_addr, len, 0);
|
|
+ if (!target_saddr)
|
|
+ return (-TARGET_EFAULT);
|
|
+ memcpy(target_saddr, addr, len);
|
|
+ target_saddr->sa_family = tswap16(addr->sa_family);
|
|
+ unlock_user(target_saddr, target_addr, len);
|
|
+
|
|
+ return (0);
|
|
+}
|
|
+
|
|
+static inline abi_long
|
|
+target_to_host_cmsg(struct msghdr *msgh, struct target_msghdr *target_msgh)
|
|
+{
|
|
+ struct cmsghdr *cmsg = CMSG_FIRSTHDR(msgh);
|
|
+ abi_long msg_controllen;
|
|
+ abi_ulong target_cmsg_addr;
|
|
+ struct target_cmsghdr *target_cmsg;
|
|
+ socklen_t space = 0;
|
|
+
|
|
+
|
|
+ msg_controllen = tswapal(target_msgh->msg_controllen);
|
|
+ if (msg_controllen < sizeof (struct target_cmsghdr))
|
|
+ goto the_end;
|
|
+ target_cmsg_addr = tswapal(target_msgh->msg_control);
|
|
+ target_cmsg = lock_user(VERIFY_READ, target_cmsg_addr,
|
|
+ msg_controllen, 1);
|
|
+ if (!target_cmsg)
|
|
+ return (-TARGET_EFAULT);
|
|
+ while (cmsg && target_cmsg) {
|
|
+ void *data = CMSG_DATA(cmsg);
|
|
+ void *target_data = TARGET_CMSG_DATA(target_cmsg);
|
|
+ int len = tswapal(target_cmsg->cmsg_len) -
|
|
+ TARGET_CMSG_ALIGN(sizeof (struct target_cmsghdr));
|
|
+ space += CMSG_SPACE(len);
|
|
+ if (space > msgh->msg_controllen) {
|
|
+ space -= CMSG_SPACE(len);
|
|
+ gemu_log("Host cmsg overflow\n");
|
|
+ break;
|
|
+ }
|
|
+ cmsg->cmsg_level = tswap32(target_cmsg->cmsg_level);
|
|
+ cmsg->cmsg_type = tswap32(target_cmsg->cmsg_type);
|
|
+ cmsg->cmsg_len = CMSG_LEN(len);
|
|
+
|
|
+ if (cmsg->cmsg_level != TARGET_SOL_SOCKET ||
|
|
+ cmsg->cmsg_type != SCM_RIGHTS) {
|
|
+ gemu_log("Unsupported ancillary data: %d/%d\n",
|
|
+ cmsg->cmsg_level, cmsg->cmsg_type);
|
|
+ memcpy(data, target_data, len);
|
|
+ } else {
|
|
+ int *fd = (int *)data;
|
|
+ int *target_fd = (int *)target_data;
|
|
+ int i, numfds = len / sizeof(int);
|
|
+
|
|
+ for (i = 0; i < numfds; i++)
|
|
+ fd[i] = tswap32(target_fd[i]);
|
|
+ }
|
|
+ cmsg = CMSG_NXTHDR(msgh, cmsg);
|
|
+ target_cmsg = TARGET_CMSG_NXTHDR(target_msgh, target_cmsg);
|
|
+ }
|
|
+ unlock_user(target_cmsg, target_cmsg_addr, 0);
|
|
+
|
|
+the_end:
|
|
+ msgh->msg_controllen = space;
|
|
+ return (0);
|
|
+}
|
|
+
|
|
+static inline abi_long
|
|
+host_to_target_cmsg(struct target_msghdr *target_msgh, struct msghdr *msgh)
|
|
+{
|
|
+ struct cmsghdr *cmsg = CMSG_FIRSTHDR(msgh);
|
|
+ abi_long msg_controllen;
|
|
+ abi_ulong target_cmsg_addr;
|
|
+ struct target_cmsghdr *target_cmsg;
|
|
+ socklen_t space = 0;
|
|
+
|
|
+ msg_controllen = tswapal(target_msgh->msg_controllen);
|
|
+ if (msg_controllen < sizeof (struct target_cmsghdr))
|
|
+ goto the_end;
|
|
+ target_cmsg_addr = tswapal(target_msgh->msg_control);
|
|
+ target_cmsg = lock_user(VERIFY_WRITE, target_cmsg_addr,
|
|
+ msg_controllen, 0);
|
|
+ if (!target_cmsg)
|
|
+ return (-TARGET_EFAULT);
|
|
+ while (cmsg && target_cmsg) {
|
|
+ void *data = CMSG_DATA(cmsg);
|
|
+ void *target_data = TARGET_CMSG_DATA(target_cmsg);
|
|
+ int len = cmsg->cmsg_len - CMSG_ALIGN(sizeof (struct cmsghdr));
|
|
+
|
|
+ space += TARGET_CMSG_SPACE(len);
|
|
+ if (space > msg_controllen) {
|
|
+ space -= TARGET_CMSG_SPACE(len);
|
|
+ gemu_log("Target cmsg overflow\n");
|
|
+ break;
|
|
+ }
|
|
+ target_cmsg->cmsg_level = tswap32(cmsg->cmsg_level);
|
|
+ target_cmsg->cmsg_type = tswap32(cmsg->cmsg_type);
|
|
+ target_cmsg->cmsg_len = tswapal(TARGET_CMSG_LEN(len));
|
|
+ if ((cmsg->cmsg_level == TARGET_SOL_SOCKET) &&
|
|
+ (cmsg->cmsg_type == SCM_RIGHTS)) {
|
|
+ int *fd = (int *)data;
|
|
+ int *target_fd = (int *)target_data;
|
|
+ int i, numfds = len / sizeof(int);
|
|
+ for (i = 0; i < numfds; i++)
|
|
+ target_fd[i] = tswap32(fd[i]);
|
|
+ } else if ((cmsg->cmsg_level == TARGET_SOL_SOCKET) &&
|
|
+ (cmsg->cmsg_type == SO_TIMESTAMP) &&
|
|
+ (len == sizeof(struct timeval))) {
|
|
+ /* copy struct timeval to target */
|
|
+ struct timeval *tv = (struct timeval *)data;
|
|
+ struct target_timeval *target_tv =
|
|
+ (struct target_timeval *)target_data;
|
|
+ target_tv->tv_sec = tswapal(tv->tv_sec);
|
|
+ target_tv->tv_usec = tswapal(tv->tv_usec);
|
|
+ } else {
|
|
+ gemu_log("Unsupported ancillary data: %d/%d\n",
|
|
+ cmsg->cmsg_level, cmsg->cmsg_type);
|
|
+ memcpy(target_data, data, len);
|
|
+ }
|
|
+ cmsg = CMSG_NXTHDR(msgh, cmsg);
|
|
+ target_cmsg = TARGET_CMSG_NXTHDR(target_msgh, target_cmsg);
|
|
+ }
|
|
+ unlock_user(target_cmsg, target_cmsg_addr, space);
|
|
+
|
|
+the_end:
|
|
+ target_msgh->msg_controllen = tswapal(space);
|
|
+ return (0);
|
|
+}
|
|
+
|
|
+static inline rlim_t
|
|
+target_to_host_rlim(abi_ulong target_rlim)
|
|
+{
|
|
+ abi_ulong target_rlim_swap;
|
|
+ rlim_t result;
|
|
+
|
|
+ target_rlim_swap = tswapal(target_rlim);
|
|
+ if (target_rlim_swap == TARGET_RLIM_INFINITY)
|
|
+ return (RLIM_INFINITY);
|
|
+
|
|
+ result = target_rlim_swap;
|
|
+ if (target_rlim_swap != (rlim_t)result)
|
|
+ return (RLIM_INFINITY);
|
|
+
|
|
+ return (result);
|
|
+}
|
|
+
|
|
+static inline abi_ulong
|
|
+host_to_target_rlim(rlim_t rlim)
|
|
+{
|
|
+ abi_ulong target_rlim_swap;
|
|
+ abi_ulong result;
|
|
+
|
|
+ if (rlim == RLIM_INFINITY || rlim != (abi_long)rlim)
|
|
+ target_rlim_swap = TARGET_RLIM_INFINITY;
|
|
+ else
|
|
+ target_rlim_swap = rlim;
|
|
+ result = tswapal(target_rlim_swap);
|
|
+
|
|
+ return (result);
|
|
+}
|
|
+
|
|
+static inline int
|
|
+target_to_host_resource(int code)
|
|
+{
|
|
+
|
|
+ switch (code) {
|
|
+ case TARGET_RLIMIT_AS:
|
|
+ return RLIMIT_AS;
|
|
+
|
|
+ case TARGET_RLIMIT_CORE:
|
|
+ return RLIMIT_CORE;
|
|
+
|
|
+ case TARGET_RLIMIT_CPU:
|
|
+ return RLIMIT_CPU;
|
|
+
|
|
+ case TARGET_RLIMIT_DATA:
|
|
+ return RLIMIT_DATA;
|
|
+
|
|
+ case TARGET_RLIMIT_FSIZE:
|
|
+ return RLIMIT_FSIZE;
|
|
+
|
|
+ case TARGET_RLIMIT_MEMLOCK:
|
|
+ return RLIMIT_MEMLOCK;
|
|
+
|
|
+ case TARGET_RLIMIT_NOFILE:
|
|
+ return RLIMIT_NOFILE;
|
|
+
|
|
+ case TARGET_RLIMIT_NPROC:
|
|
+ return RLIMIT_NPROC;
|
|
+
|
|
+ case TARGET_RLIMIT_RSS:
|
|
+ return RLIMIT_RSS;
|
|
+
|
|
+ case TARGET_RLIMIT_SBSIZE:
|
|
+ return RLIMIT_SBSIZE;
|
|
+
|
|
+ case TARGET_RLIMIT_STACK:
|
|
+ return RLIMIT_STACK;
|
|
+
|
|
+ case TARGET_RLIMIT_SWAP:
|
|
+ return RLIMIT_SWAP;
|
|
+
|
|
+ case TARGET_RLIMIT_NPTS:
|
|
+ return RLIMIT_NPTS;
|
|
+
|
|
+ default:
|
|
+ return (code);
|
|
+ }
|
|
+}
|
|
+
|
|
+static int
|
|
+target_to_host_fcntl_cmd(int cmd)
|
|
+{
|
|
+
|
|
+ switch(cmd) {
|
|
+ case TARGET_F_DUPFD:
|
|
+ return F_DUPFD;
|
|
+
|
|
+ case TARGET_F_DUP2FD:
|
|
+ return F_DUP2FD;
|
|
+
|
|
+ case TARGET_F_GETFD:
|
|
+ return F_GETFD;
|
|
+
|
|
+ case TARGET_F_SETFD:
|
|
+ return F_SETFD;
|
|
+
|
|
+ case TARGET_F_GETFL:
|
|
+ return F_GETFL;
|
|
+
|
|
+ case TARGET_F_SETFL:
|
|
+ return F_SETFL;
|
|
+
|
|
+ case TARGET_F_GETOWN:
|
|
+ return F_GETOWN;
|
|
+
|
|
+ case TARGET_F_SETOWN:
|
|
+ return F_SETOWN;
|
|
+
|
|
+ case TARGET_F_GETLK:
|
|
+ return F_GETLK;
|
|
+
|
|
+ case TARGET_F_SETLK:
|
|
+ return F_SETLK;
|
|
+
|
|
+ case TARGET_F_SETLKW:
|
|
+ return F_SETLKW;
|
|
+
|
|
+ case TARGET_F_READAHEAD:
|
|
+ return F_READAHEAD;
|
|
+
|
|
+ case TARGET_F_RDAHEAD:
|
|
+ return F_RDAHEAD;
|
|
+
|
|
+ default:
|
|
+ return (cmd);
|
|
+ }
|
|
+}
|
|
+
|
|
+static inline abi_long
|
|
+host_to_target_rusage(abi_ulong target_addr, const struct rusage *rusage)
|
|
+{
|
|
+ struct target_rusage *target_rusage;
|
|
+
|
|
+ if (!lock_user_struct(VERIFY_WRITE, target_rusage, target_addr, 0))
|
|
+ return (-TARGET_EFAULT);
|
|
+ target_rusage->ru_utime.tv_sec = tswapal(rusage->ru_utime.tv_sec);
|
|
+ target_rusage->ru_utime.tv_usec = tswapal(rusage->ru_utime.tv_usec);
|
|
+ target_rusage->ru_stime.tv_sec = tswapal(rusage->ru_stime.tv_sec);
|
|
+ target_rusage->ru_stime.tv_usec = tswapal(rusage->ru_stime.tv_usec);
|
|
+ target_rusage->ru_maxrss = tswapal(rusage->ru_maxrss);
|
|
+ target_rusage->ru_ixrss = tswapal(rusage->ru_ixrss);
|
|
+ target_rusage->ru_idrss = tswapal(rusage->ru_idrss);
|
|
+ target_rusage->ru_isrss = tswapal(rusage->ru_isrss);
|
|
+ target_rusage->ru_minflt = tswapal(rusage->ru_minflt);
|
|
+ target_rusage->ru_majflt = tswapal(rusage->ru_majflt);
|
|
+ target_rusage->ru_nswap = tswapal(rusage->ru_nswap);
|
|
+ target_rusage->ru_inblock = tswapal(rusage->ru_inblock);
|
|
+ target_rusage->ru_oublock = tswapal(rusage->ru_oublock);
|
|
+ target_rusage->ru_msgsnd = tswapal(rusage->ru_msgsnd);
|
|
+ target_rusage->ru_msgrcv = tswapal(rusage->ru_msgrcv);
|
|
+ target_rusage->ru_nsignals = tswapal(rusage->ru_nsignals);
|
|
+ target_rusage->ru_nvcsw = tswapal(rusage->ru_nvcsw);
|
|
+ target_rusage->ru_nivcsw = tswapal(rusage->ru_nivcsw);
|
|
+ unlock_user_struct(target_rusage, target_addr, 1);
|
|
+
|
|
+ return (0);
|
|
+}
|
|
+
|
|
+/*
|
|
+ * Map host to target signal numbers for the wait family of syscalls.
|
|
+ * Assume all other status bits are the same.
|
|
+ */
|
|
+static int
|
|
+host_to_target_waitstatus(int status)
|
|
+{
|
|
+ if (WIFSIGNALED(status)) {
|
|
+ return (host_to_target_signal(WTERMSIG(status)) |
|
|
+ (status & ~0x7f));
|
|
+ }
|
|
+ if (WIFSTOPPED(status)) {
|
|
+ return (host_to_target_signal(WSTOPSIG(status)) << 8) |
|
|
+ (status & 0xff);
|
|
+ }
|
|
+ return (status);
|
|
+}
|
|
+
|
|
+static inline abi_long
|
|
+copy_from_user_timeval(struct timeval *tv, abi_ulong target_tv_addr)
|
|
+{
|
|
+ struct target_freebsd_timeval *target_tv;
|
|
+
|
|
+ if (!lock_user_struct(VERIFY_READ, target_tv, target_tv_addr, 0))
|
|
+ return -TARGET_EFAULT;
|
|
+ __get_user(tv->tv_sec, &target_tv->tv_sec);
|
|
+ __get_user(tv->tv_usec, &target_tv->tv_usec);
|
|
+ unlock_user_struct(target_tv, target_tv_addr, 1);
|
|
+ return (0);
|
|
+}
|
|
+
|
|
+static inline abi_long
|
|
+target_to_host_timespec(struct timespec *ts, abi_ulong target_ts_addr)
|
|
+{
|
|
+ struct target_freebsd_timespec *target_ts;
|
|
+
|
|
+ if (!lock_user_struct(VERIFY_READ, target_ts, target_ts_addr, 0))
|
|
+ return -TARGET_EFAULT;
|
|
+ __get_user(ts->tv_sec, &target_ts->tv_sec);
|
|
+ __get_user(ts->tv_nsec, &target_ts->tv_nsec);
|
|
+ unlock_user_struct(target_ts, target_ts_addr, 1);
|
|
+ return (0);
|
|
+}
|
|
+
|
|
+static inline abi_long
|
|
+fbsd_copy_to_user_timeval(struct timeval *tv, abi_ulong target_tv_addr)
|
|
+{
|
|
+ struct target_freebsd_timeval *target_tv;
|
|
+
|
|
+ if (!lock_user_struct(VERIFY_WRITE, target_tv, target_tv_addr, 0))
|
|
+ return -TARGET_EFAULT;
|
|
+ __put_user(tv->tv_sec, &target_tv->tv_sec);
|
|
+ __put_user(tv->tv_usec, &target_tv->tv_usec);
|
|
+ unlock_user_struct(target_tv, target_tv_addr, 1);
|
|
+ return (0);
|
|
+}
|
|
+
|
|
+static inline abi_long
|
|
+host_to_target_timespec(abi_ulong target_ts_addr, struct timespec *ts)
|
|
+{
|
|
+ struct target_freebsd_timespec *target_ts;
|
|
+
|
|
+ if (!lock_user_struct(VERIFY_WRITE, target_ts, target_ts_addr, 0))
|
|
+ return -TARGET_EFAULT;
|
|
+ __put_user(ts->tv_sec, &target_ts->tv_sec);
|
|
+ __put_user(ts->tv_nsec, &target_ts->tv_nsec);
|
|
+ unlock_user_struct(target_ts, target_ts_addr, 1);
|
|
+ return (0);
|
|
+}
|
|
+static inline abi_ulong
|
|
+copy_from_user_fdset(fd_set *fds, abi_ulong target_fds_addr, int n)
|
|
+{
|
|
+ int i, nw, j, k;
|
|
+ abi_ulong b, *target_fds;
|
|
+
|
|
+ nw = (n + TARGET_ABI_BITS - 1) / TARGET_ABI_BITS;
|
|
+ if (!(target_fds = lock_user(VERIFY_READ, target_fds_addr,
|
|
+ sizeof(abi_ulong) * nw, 1)))
|
|
+ return (-TARGET_EFAULT);
|
|
+
|
|
+ FD_ZERO(fds);
|
|
+ k = 0;
|
|
+ for (i = 0; i < nw; i++) {
|
|
+ /* grab the abi_ulong */
|
|
+ __get_user(b, &target_fds[i]);
|
|
+ for (j = 0; j < TARGET_ABI_BITS; j++) {
|
|
+ /* check the bit inside the abi_ulong */
|
|
+ if ((b >> j) & 1)
|
|
+ FD_SET(k, fds);
|
|
+ k++;
|
|
+ }
|
|
+ }
|
|
+
|
|
+ unlock_user(target_fds, target_fds_addr, 0);
|
|
+
|
|
+ return (0);
|
|
+}
|
|
+
|
|
+static inline abi_ulong
|
|
+copy_from_user_fdset_ptr(fd_set *fds, fd_set **fds_ptr,
|
|
+ abi_ulong target_fds_addr, int n)
|
|
+{
|
|
+ if (target_fds_addr) {
|
|
+ if (copy_from_user_fdset(fds, target_fds_addr, n))
|
|
+ return (-TARGET_EFAULT);
|
|
+ *fds_ptr = fds;
|
|
+ } else {
|
|
+ *fds_ptr = NULL;
|
|
+ }
|
|
+ return (0);
|
|
+}
|
|
+
|
|
+static inline abi_long
|
|
+copy_to_user_fdset(abi_ulong target_fds_addr, const fd_set *fds, int n)
|
|
+{
|
|
+ int i, nw, j, k;
|
|
+ abi_long v;
|
|
+ abi_ulong *target_fds;
|
|
+
|
|
+ nw = (n + TARGET_ABI_BITS - 1) / TARGET_ABI_BITS;
|
|
+ if (!(target_fds = lock_user(VERIFY_WRITE, target_fds_addr,
|
|
+ sizeof(abi_ulong) * nw, 0)))
|
|
+ return (-TARGET_EFAULT);
|
|
+
|
|
+ k = 0;
|
|
+ for (i = 0; i < nw; i++) {
|
|
+ v = 0;
|
|
+ for (j = 0; j < TARGET_ABI_BITS; j++) {
|
|
+ v |= ((FD_ISSET(k, fds) != 0) << j);
|
|
+ k++;
|
|
+ }
|
|
+ __put_user(v, &target_fds[i]);
|
|
+ }
|
|
+
|
|
+ unlock_user(target_fds, target_fds_addr, sizeof(abi_ulong) * nw);
|
|
+
|
|
+ return (0);
|
|
+}
|
|
+
|
|
+#if TARGET_ABI_BITS == 32
|
|
+static inline uint64_t
|
|
+target_offset64(uint32_t word0, uint32_t word1)
|
|
+{
|
|
+#ifdef TARGET_WORDS_BIGENDIAN
|
|
+ return ((uint64_t)word0 << 32) | word1;
|
|
+#else
|
|
+ return ((uint64_t)word1 << 32) | word0;
|
|
#endif
|
|
- gdb_exit(cpu_env, arg1);
|
|
- /* XXX: should free thread stack and CPU env */
|
|
- _exit(arg1);
|
|
- ret = 0; /* avoid warning */
|
|
- break;
|
|
- case TARGET_FREEBSD_NR_read:
|
|
- if (!(p = lock_user(VERIFY_WRITE, arg2, arg3, 0)))
|
|
- goto efault;
|
|
- ret = get_errno(read(arg1, p, arg3));
|
|
- unlock_user(p, arg2, ret);
|
|
- break;
|
|
- case TARGET_FREEBSD_NR_write:
|
|
- if (!(p = lock_user(VERIFY_READ, arg2, arg3, 1)))
|
|
- goto efault;
|
|
- ret = get_errno(write(arg1, p, arg3));
|
|
- unlock_user(p, arg2, 0);
|
|
- break;
|
|
- case TARGET_FREEBSD_NR_writev:
|
|
- {
|
|
- int count = arg3;
|
|
- struct iovec *vec;
|
|
+}
|
|
+#else /* TARGET_ABI_BITS != 32 */
|
|
+static inline uint64_t
|
|
+target_offset64(uint64_t word0, uint64_t word1)
|
|
+{
|
|
+ return (word0);
|
|
+}
|
|
+#endif /* TARGET_ABI_BITS != 32 */
|
|
|
|
- vec = alloca(count * sizeof(struct iovec));
|
|
- if (lock_iovec(VERIFY_READ, vec, arg2, count, 1) < 0)
|
|
- goto efault;
|
|
- ret = get_errno(writev(arg1, vec, count));
|
|
- unlock_iovec(vec, arg2, count, 0);
|
|
- }
|
|
- break;
|
|
- case TARGET_FREEBSD_NR_open:
|
|
- if (!(p = lock_user_string(arg1)))
|
|
- goto efault;
|
|
- ret = get_errno(open(path(p),
|
|
- target_to_host_bitmask(arg2, fcntl_flags_tbl),
|
|
- arg3));
|
|
- unlock_user(p, arg1, 0);
|
|
- break;
|
|
- case TARGET_FREEBSD_NR_mmap:
|
|
- ret = get_errno(target_mmap(arg1, arg2, arg3,
|
|
- target_to_host_bitmask(arg4, mmap_flags_tbl),
|
|
- arg5,
|
|
- arg6));
|
|
- break;
|
|
- case TARGET_FREEBSD_NR_munmap:
|
|
- ret = get_errno(target_munmap(arg1, arg2));
|
|
- break;
|
|
- case TARGET_FREEBSD_NR_mprotect:
|
|
- ret = get_errno(target_mprotect(arg1, arg2, arg3));
|
|
- break;
|
|
- case TARGET_FREEBSD_NR_break:
|
|
- ret = do_obreak(arg1);
|
|
- break;
|
|
-#ifdef __FreeBSD__
|
|
- case TARGET_FREEBSD_NR___sysctl:
|
|
- ret = do_freebsd_sysctl(arg1, arg2, arg3, arg4, arg5, arg6);
|
|
- break;
|
|
+/* ARM EABI and MIPS expect 64bit types aligned even on pairs of registers */
|
|
+#ifdef TARGET_ARM
|
|
+static inline int
|
|
+regpairs_aligned(void *cpu_env) {
|
|
+
|
|
+ return ((((CPUARMState *)cpu_env)->eabi) == 1);
|
|
+}
|
|
+#elif defined(TARGET_MIPS) && TARGET_ABI_BITS == 32
|
|
+static inline int
|
|
+regpairs_aligned(void *cpu_env) { return 1; }
|
|
+#else
|
|
+static inline int
|
|
+regpairs_aligned(void *cpu_env) { return 0; }
|
|
#endif
|
|
- case TARGET_FREEBSD_NR_sysarch:
|
|
- ret = do_freebsd_sysarch(cpu_env, arg1, arg2);
|
|
- break;
|
|
- case TARGET_FREEBSD_NR_syscall:
|
|
- case TARGET_FREEBSD_NR___syscall:
|
|
- ret = do_freebsd_syscall(cpu_env,arg1 & 0xffff,arg2,arg3,arg4,arg5,arg6,arg7,arg8,0);
|
|
- break;
|
|
+
|
|
+static inline abi_long
|
|
+unimplemented(int num)
|
|
+{
|
|
+
|
|
+ qemu_log("qemu: Unsupported syscall: %d\n", num);
|
|
+ return (-TARGET_ENOSYS);
|
|
+}
|
|
+
|
|
+/* do_bind() must return target values and target errnos. */
|
|
+static abi_long
|
|
+do_bind(int sockfd, abi_ulong target_addr, socklen_t addrlen)
|
|
+{
|
|
+ abi_long ret;
|
|
+ void *addr;
|
|
+
|
|
+ if ((int)addrlen < 0)
|
|
+ return (-TARGET_EINVAL);
|
|
+
|
|
+ addr = alloca(addrlen + 1);
|
|
+ ret = target_to_host_sockaddr(addr, target_addr, addrlen);
|
|
+ if (ret)
|
|
+ return (ret);
|
|
+
|
|
+ return get_errno(bind(sockfd, addr, addrlen));
|
|
+}
|
|
+
|
|
+/* do_connect() must return target values and target errnos. */
|
|
+static abi_long
|
|
+do_connect(int sockfd, abi_ulong target_addr, socklen_t addrlen)
|
|
+{
|
|
+ abi_long ret;
|
|
+ void *addr;
|
|
+
|
|
+ if ((int)addrlen < 0)
|
|
+ return (-TARGET_EINVAL);
|
|
+
|
|
+ addr = alloca(addrlen);
|
|
+
|
|
+ ret = target_to_host_sockaddr(addr, target_addr, addrlen);
|
|
+
|
|
+ if (ret)
|
|
+ return (ret);
|
|
+
|
|
+ return (get_errno(connect(sockfd, addr, addrlen)));
|
|
+}
|
|
+
|
|
+/* do_sendrecvmsg() must return target values and target errnos. */
|
|
+static abi_long
|
|
+do_sendrecvmsg(int fd, abi_ulong target_msg, int flags, int send)
|
|
+{
|
|
+ abi_long ret, len;
|
|
+ struct target_msghdr *msgp;
|
|
+ struct msghdr msg;
|
|
+ int count;
|
|
+ struct iovec *vec;
|
|
+ abi_ulong target_vec;
|
|
+
|
|
+ if (!lock_user_struct(send ? VERIFY_READ : VERIFY_WRITE, msgp,
|
|
+ target_msg, send ? 1 : 0))
|
|
+ return (-TARGET_EFAULT);
|
|
+ if (msgp->msg_name) {
|
|
+ msg.msg_namelen = tswap32(msgp->msg_namelen);
|
|
+ msg.msg_name = alloca(msg.msg_namelen);
|
|
+ ret = target_to_host_sockaddr(msg.msg_name,
|
|
+ tswapal(msgp->msg_name), msg.msg_namelen);
|
|
+
|
|
+ if (ret) {
|
|
+ unlock_user_struct(msgp, target_msg, send ? 0 : 1);
|
|
+ return (ret);
|
|
+ }
|
|
+ } else {
|
|
+ msg.msg_name = NULL;
|
|
+ msg.msg_namelen = 0;
|
|
+ }
|
|
+ msg.msg_controllen = 2 * tswapal(msgp->msg_controllen);
|
|
+ msg.msg_control = alloca(msg.msg_controllen);
|
|
+ msg.msg_flags = tswap32(msgp->msg_flags);
|
|
+
|
|
+ count = tswapal(msgp->msg_iovlen);
|
|
+ vec = alloca(count * sizeof(struct iovec));
|
|
+ target_vec = tswapal(msgp->msg_iov);
|
|
+ lock_iovec(send ? VERIFY_READ : VERIFY_WRITE, vec, target_vec, count,
|
|
+ send);
|
|
+ msg.msg_iovlen = count;
|
|
+ msg.msg_iov = vec;
|
|
+
|
|
+ if (send) {
|
|
+ ret = target_to_host_cmsg(&msg, msgp);
|
|
+ if (0 == ret)
|
|
+ ret = get_errno(sendmsg(fd, &msg, flags));
|
|
+ } else {
|
|
+ ret = get_errno(recvmsg(fd, &msg, flags));
|
|
+ if (!is_error(ret)) {
|
|
+ len = ret;
|
|
+ ret = host_to_target_cmsg(msgp, &msg);
|
|
+ if (!is_error(ret)) {
|
|
+ msgp->msg_namelen = tswap32(msg.msg_namelen);
|
|
+ if (msg.msg_name != NULL) {
|
|
+ ret = host_to_target_sockaddr(
|
|
+ tswapal(msgp->msg_name),
|
|
+ msg.msg_name, msg.msg_namelen);
|
|
+ if (ret)
|
|
+ goto out;
|
|
+ }
|
|
+ }
|
|
+ ret = len;
|
|
+ }
|
|
+ }
|
|
+out:
|
|
+ unlock_iovec(vec, target_vec, count, !send);
|
|
+ unlock_user_struct(msgp, target_msg, send ? 0 : 1);
|
|
+ return (ret);
|
|
+}
|
|
+
|
|
+/* do_accept() must return target values and target errnos. */
|
|
+static abi_long
|
|
+do_accept(int fd, abi_ulong target_addr, abi_ulong target_addrlen_addr)
|
|
+{
|
|
+ socklen_t addrlen;
|
|
+ void *addr;
|
|
+ abi_long ret;
|
|
+
|
|
+ if (target_addr == 0)
|
|
+ return get_errno(accept(fd, NULL, NULL));
|
|
+
|
|
+ /* return EINVAL if addrlen pointer is invalid */
|
|
+ if (get_user_u32(addrlen, target_addrlen_addr))
|
|
+ return (-TARGET_EINVAL);
|
|
+
|
|
+ if ((int)addrlen < 0)
|
|
+ return (-TARGET_EINVAL);
|
|
+
|
|
+ if (!access_ok(VERIFY_WRITE, target_addr, addrlen))
|
|
+ return -TARGET_EINVAL;
|
|
+
|
|
+ addr = alloca(addrlen);
|
|
+
|
|
+ ret = get_errno(accept(fd, addr, &addrlen));
|
|
+ if (!is_error(ret)) {
|
|
+ host_to_target_sockaddr(target_addr, addr, addrlen);
|
|
+ if (put_user_u32(addrlen, target_addrlen_addr))
|
|
+ ret = (-TARGET_EFAULT);
|
|
+ }
|
|
+ return (ret);
|
|
+}
|
|
+
|
|
+/* do_getpeername() must return target values and target errnos. */
|
|
+static abi_long
|
|
+do_getpeername(int fd, abi_ulong target_addr, abi_ulong target_addrlen_addr)
|
|
+{
|
|
+ socklen_t addrlen;
|
|
+ void *addr;
|
|
+ abi_long ret;
|
|
+ if (get_user_u32(addrlen, target_addrlen_addr))
|
|
+ return (-TARGET_EFAULT);
|
|
+ if ((int)addrlen < 0) {
|
|
+ return (-TARGET_EINVAL);
|
|
+ }
|
|
+ if (!access_ok(VERIFY_WRITE, target_addr, addrlen))
|
|
+ return (-TARGET_EFAULT);
|
|
+ addr = alloca(addrlen);
|
|
+ ret = get_errno(getpeername(fd, addr, &addrlen));
|
|
+ if (!is_error(ret)) {
|
|
+ host_to_target_sockaddr(target_addr, addr, addrlen);
|
|
+ if (put_user_u32(addrlen, target_addrlen_addr))
|
|
+ ret = (-TARGET_EFAULT);
|
|
+ }
|
|
+ return (ret);
|
|
+}
|
|
+
|
|
+/* do_getsockname() must return target values and target errnos. */
|
|
+static abi_long
|
|
+do_getsockname(int fd, abi_ulong target_addr, abi_ulong target_addrlen_addr)
|
|
+{
|
|
+ socklen_t addrlen;
|
|
+ void *addr;
|
|
+ abi_long ret;
|
|
+
|
|
+ if (get_user_u32(addrlen, target_addrlen_addr))
|
|
+ return (-TARGET_EFAULT);
|
|
+
|
|
+ if ((int)addrlen < 0)
|
|
+ return (-TARGET_EINVAL);
|
|
+
|
|
+ if (!access_ok(VERIFY_WRITE, target_addr, addrlen))
|
|
+ return (-TARGET_EFAULT);
|
|
+
|
|
+ addr = alloca(addrlen);
|
|
+
|
|
+ ret = get_errno(getsockname(fd, addr, &addrlen));
|
|
+ if (!is_error(ret)) {
|
|
+ host_to_target_sockaddr(target_addr, addr, addrlen);
|
|
+ if (put_user_u32(addrlen, target_addrlen_addr))
|
|
+ ret = (-TARGET_EFAULT);
|
|
+ }
|
|
+ return (ret);
|
|
+}
|
|
+
|
|
+/* do_socketpair() must return target values and target errnos. */
|
|
+static abi_long
|
|
+do_socketpair(int domain, int type, int protocol, abi_ulong target_tab_addr)
|
|
+{
|
|
+ int tab[2];
|
|
+ abi_long ret;
|
|
+
|
|
+ ret = get_errno(socketpair(domain, type, protocol, tab));
|
|
+ if (!is_error(ret)) {
|
|
+ if (put_user_s32(tab[0], target_tab_addr)
|
|
+ || put_user_s32(tab[1], target_tab_addr + sizeof(tab[0])))
|
|
+ ret = (-TARGET_EFAULT);
|
|
+ }
|
|
+ return (ret);
|
|
+}
|
|
+
|
|
+/* do_sendto() must return target values and target errnos. */
|
|
+static abi_long
|
|
+do_sendto(int fd, abi_ulong msg, size_t len, int flags, abi_ulong target_addr,
|
|
+ socklen_t addrlen)
|
|
+{
|
|
+ void *addr;
|
|
+ void *host_msg;
|
|
+ abi_long ret;
|
|
+
|
|
+ if ((int)addrlen < 0)
|
|
+ return (-TARGET_EINVAL);
|
|
+ host_msg = lock_user(VERIFY_READ, msg, len, 1);
|
|
+ if (!host_msg)
|
|
+ return (-TARGET_EFAULT);
|
|
+ if (target_addr) {
|
|
+ addr = alloca(addrlen);
|
|
+ ret = target_to_host_sockaddr(addr, target_addr, addrlen);
|
|
+ if (ret) {
|
|
+ unlock_user(host_msg, msg, 0);
|
|
+ return (ret);
|
|
+ }
|
|
+ ret = get_errno(sendto(fd, host_msg, len, flags, addr,
|
|
+ addrlen));
|
|
+ } else {
|
|
+ ret = get_errno(send(fd, host_msg, len, flags));
|
|
+ }
|
|
+ unlock_user(host_msg, msg, 0);
|
|
+ return (ret);
|
|
+}
|
|
+
|
|
+/* do_recvfrom() must return target values and target errnos. */
|
|
+static abi_long
|
|
+do_recvfrom(int fd, abi_ulong msg, size_t len, int flags, abi_ulong target_addr,
|
|
+ abi_ulong target_addrlen)
|
|
+{
|
|
+ socklen_t addrlen;
|
|
+ void *addr;
|
|
+ void *host_msg;
|
|
+ abi_long ret;
|
|
+
|
|
+ host_msg = lock_user(VERIFY_WRITE, msg, len, 0);
|
|
+ if (!host_msg)
|
|
+ return (-TARGET_EFAULT);
|
|
+ if (target_addr) {
|
|
+ if (get_user_u32(addrlen, target_addrlen)) {
|
|
+ ret = -TARGET_EFAULT;
|
|
+ goto fail;
|
|
+ }
|
|
+ if ((int)addrlen < 0) {
|
|
+ ret = (-TARGET_EINVAL);
|
|
+ goto fail;
|
|
+ }
|
|
+ addr = alloca(addrlen);
|
|
+ ret = get_errno(recvfrom(fd, host_msg, len, flags, addr,
|
|
+ &addrlen));
|
|
+ } else {
|
|
+ addr = NULL; /* To keep compiler quiet. */
|
|
+ ret = get_errno(qemu_recv(fd, host_msg, len, flags));
|
|
+ }
|
|
+ if (!is_error(ret)) {
|
|
+ if (target_addr) {
|
|
+ host_to_target_sockaddr(target_addr, addr, addrlen);
|
|
+ if (put_user_u32(addrlen, target_addrlen)) {
|
|
+ ret = -TARGET_EFAULT;
|
|
+ goto fail;
|
|
+ }
|
|
+ }
|
|
+ unlock_user(host_msg, msg, len);
|
|
+ } else {
|
|
+fail:
|
|
+ unlock_user(host_msg, msg, 0);
|
|
+ }
|
|
+ return (ret);
|
|
+}
|
|
+
|
|
+/* do_freebsd_select() must return target values and target errnos. */
|
|
+static abi_long
|
|
+do_freebsd_select(int n, abi_ulong rfd_addr, abi_ulong wfd_addr,
|
|
+ abi_ulong efd_addr, abi_ulong target_tv_addr)
|
|
+{
|
|
+ fd_set rfds, wfds, efds;
|
|
+ fd_set *rfds_ptr, *wfds_ptr, *efds_ptr;
|
|
+ struct timeval tv, *tv_ptr;
|
|
+ abi_long ret;
|
|
+
|
|
+ if ((ret = copy_from_user_fdset_ptr(&rfds, &rfds_ptr, rfd_addr, n)) != 0)
|
|
+ return (ret);
|
|
+ if ((ret = copy_from_user_fdset_ptr(&wfds, &wfds_ptr, wfd_addr, n)) != 0)
|
|
+ return (ret);
|
|
+ if ((ret = copy_from_user_fdset_ptr(&efds, &efds_ptr, efd_addr, n)) != 0)
|
|
+ return (ret);
|
|
+
|
|
+ if (target_tv_addr) {
|
|
+ if (copy_from_user_timeval(&tv, target_tv_addr))
|
|
+ return (-TARGET_EFAULT);
|
|
+ tv_ptr = &tv;
|
|
+ } else {
|
|
+ tv_ptr = NULL;
|
|
+ }
|
|
+
|
|
+ ret = get_errno(select(n, rfds_ptr, wfds_ptr, efds_ptr, tv_ptr));
|
|
+
|
|
+ if (!is_error(ret)) {
|
|
+ if (rfd_addr && copy_to_user_fdset(rfd_addr, &rfds, n))
|
|
+ return (-TARGET_EFAULT);
|
|
+ if (wfd_addr && copy_to_user_fdset(wfd_addr, &wfds, n))
|
|
+ return (-TARGET_EFAULT);
|
|
+ if (efd_addr && copy_to_user_fdset(efd_addr, &efds, n))
|
|
+ return (-TARGET_EFAULT);
|
|
+
|
|
+ if (target_tv_addr &&
|
|
+ fbsd_copy_to_user_timeval(&tv, target_tv_addr))
|
|
+ return (-TARGET_EFAULT);
|
|
+ }
|
|
+
|
|
+ return (ret);
|
|
+}
|
|
+
|
|
+/* do_freebsd_pselect() must return target values and target errnos. */
|
|
+static abi_long
|
|
+do_freebsd_pselect(int n, abi_ulong rfd_addr, abi_ulong wfd_addr,
|
|
+ abi_ulong efd_addr, abi_ulong ts_addr, abi_ulong set_addr)
|
|
+{
|
|
+ fd_set rfds, wfds, efds;
|
|
+ fd_set *rfds_ptr, *wfds_ptr, *efds_ptr;
|
|
+ sigset_t set, *set_ptr;
|
|
+ struct timespec ts, *ts_ptr;
|
|
+ void *p;
|
|
+ abi_long ret;
|
|
+
|
|
+ ret = copy_from_user_fdset_ptr(&rfds, &rfds_ptr, rfd_addr, n);
|
|
+ if (ret)
|
|
+ return (ret);
|
|
+ ret = copy_from_user_fdset_ptr(&wfds, &wfds_ptr, wfd_addr, n);
|
|
+ if (ret)
|
|
+ return (ret);
|
|
+ ret = copy_from_user_fdset_ptr(&efds, &efds_ptr, efd_addr, n);
|
|
+ if (ret)
|
|
+ return (ret);
|
|
+
|
|
+ /* Unlike select(), pselect() uses struct timespec instead of timeval */
|
|
+ if (ts_addr) {
|
|
+ if (target_to_host_timespec(&ts, ts_addr))
|
|
+ return (-TARGET_EFAULT);
|
|
+ ts_ptr = &ts;
|
|
+ } else {
|
|
+ ts_ptr = NULL;
|
|
+ }
|
|
+
|
|
+ if (set_addr) {
|
|
+ if (!(p = lock_user(VERIFY_READ, set_addr,
|
|
+ sizeof(target_sigset_t), 1)))
|
|
+ return (-TARGET_EFAULT);
|
|
+ target_to_host_sigset(&set, p);
|
|
+ unlock_user(p, set_addr, 0);
|
|
+ set_ptr = &set;
|
|
+ } else {
|
|
+ set_ptr = NULL;
|
|
+ }
|
|
+
|
|
+ ret = get_errno(pselect(n, rfds_ptr, wfds_ptr, efds_ptr, ts_ptr,
|
|
+ set_ptr));
|
|
+
|
|
+ if (!is_error(ret)) {
|
|
+ if (rfd_addr && copy_to_user_fdset(rfd_addr, &rfds, n))
|
|
+ return (-TARGET_EFAULT);
|
|
+ if (wfd_addr && copy_to_user_fdset(wfd_addr, &wfds, n))
|
|
+ return (-TARGET_EFAULT);
|
|
+ if (efd_addr && copy_to_user_fdset(efd_addr, &efds, n))
|
|
+ return (-TARGET_EFAULT);
|
|
+
|
|
+ if (ts_addr && host_to_target_timespec(ts_addr, &ts))
|
|
+ return (-TARGET_EFAULT);
|
|
+ }
|
|
+
|
|
+ return (ret);
|
|
+}
|
|
+
|
|
+/* do_getsockopt() must return target values and target errnos. */
|
|
+static abi_long
|
|
+do_getsockopt(int sockfd, int level, int optname, abi_ulong optval_addr,
|
|
+ abi_ulong optlen)
|
|
+{
|
|
+ abi_long ret;
|
|
+ int len, val;
|
|
+ socklen_t lv;
|
|
+
|
|
+ switch(level) {
|
|
+ case TARGET_SOL_SOCKET:
|
|
+ level = SOL_SOCKET;
|
|
+ switch (optname) {
|
|
+
|
|
+ /* These don't just return a single integer */
|
|
+ case TARGET_SO_LINGER:
|
|
+ case TARGET_SO_RCVTIMEO:
|
|
+ case TARGET_SO_SNDTIMEO:
|
|
+ case TARGET_SO_ACCEPTFILTER:
|
|
+ goto unimplemented;
|
|
+
|
|
+ /* Options with 'int' argument. */
|
|
+ case TARGET_SO_DEBUG:
|
|
+ optname = SO_DEBUG;
|
|
+ goto int_case;
|
|
+
|
|
+ case TARGET_SO_REUSEADDR:
|
|
+ optname = SO_REUSEADDR;
|
|
+ goto int_case;
|
|
+
|
|
+ case TARGET_SO_REUSEPORT:
|
|
+ optname = SO_REUSEPORT;
|
|
+ goto int_case;
|
|
+
|
|
+ case TARGET_SO_TYPE:
|
|
+ optname = SO_TYPE;
|
|
+ goto int_case;
|
|
+
|
|
+ case TARGET_SO_ERROR:
|
|
+ optname = SO_ERROR;
|
|
+ goto int_case;
|
|
+
|
|
+ case TARGET_SO_DONTROUTE:
|
|
+ optname = SO_DONTROUTE;
|
|
+ goto int_case;
|
|
+
|
|
+ case TARGET_SO_BROADCAST:
|
|
+ optname = SO_BROADCAST;
|
|
+ goto int_case;
|
|
+
|
|
+ case TARGET_SO_SNDBUF:
|
|
+ optname = SO_SNDBUF;
|
|
+ goto int_case;
|
|
+
|
|
+ case TARGET_SO_RCVBUF:
|
|
+ optname = SO_RCVBUF;
|
|
+ goto int_case;
|
|
+
|
|
+ case TARGET_SO_KEEPALIVE:
|
|
+ optname = SO_KEEPALIVE;
|
|
+ goto int_case;
|
|
+
|
|
+ case TARGET_SO_OOBINLINE:
|
|
+ optname = SO_OOBINLINE;
|
|
+ goto int_case;
|
|
+
|
|
+ case TARGET_SO_TIMESTAMP:
|
|
+ optname = SO_TIMESTAMP;
|
|
+ goto int_case;
|
|
+
|
|
+ case TARGET_SO_RCVLOWAT:
|
|
+ optname = SO_RCVLOWAT;
|
|
+ goto int_case;
|
|
+
|
|
+ case TARGET_SO_LISTENINCQLEN:
|
|
+ optname = SO_LISTENINCQLEN;
|
|
+ goto int_case;
|
|
+
|
|
+ default:
|
|
+int_case:
|
|
+ if (get_user_u32(len, optlen))
|
|
+ return (-TARGET_EFAULT);
|
|
+ if (len < 0)
|
|
+ return (-TARGET_EINVAL);
|
|
+ lv = sizeof(lv);
|
|
+ ret = get_errno(getsockopt(sockfd, level, optname,
|
|
+ &val, &lv));
|
|
+ if (ret < 0)
|
|
+ return (ret);
|
|
+ if (len > lv)
|
|
+ len = lv;
|
|
+ if (len == 4) {
|
|
+ if (put_user_u32(val, optval_addr))
|
|
+ return (-TARGET_EFAULT);
|
|
+ } else {
|
|
+ if (put_user_u8(val, optval_addr))
|
|
+ return (-TARGET_EFAULT);
|
|
+ }
|
|
+ if (put_user_u32(len, optlen))
|
|
+ return (-TARGET_EFAULT);
|
|
+ break;
|
|
+
|
|
+ }
|
|
+ break;
|
|
+
|
|
+ default:
|
|
+unimplemented:
|
|
+ gemu_log("getsockopt level=%d optname=%d not yet supported\n",
|
|
+ level, optname);
|
|
+ ret = -TARGET_EOPNOTSUPP;
|
|
+ break;
|
|
+ }
|
|
+ return (ret);
|
|
+}
|
|
+
|
|
+/* do_setsockopt() must return target values and target errnos. */
|
|
+static abi_long
|
|
+do_setsockopt(int sockfd, int level, int optname, abi_ulong optval_addr,
|
|
+ socklen_t optlen)
|
|
+{
|
|
+ int val;
|
|
+ abi_long ret;
|
|
+
|
|
+ switch(level) {
|
|
+ case TARGET_SOL_SOCKET:
|
|
+ switch (optname) {
|
|
+ /* Options with 'int' argument. */
|
|
+ case TARGET_SO_DEBUG:
|
|
+ optname = SO_DEBUG;
|
|
+ break;
|
|
+
|
|
+ case TARGET_SO_REUSEADDR:
|
|
+ optname = SO_REUSEADDR;
|
|
+ break;
|
|
+
|
|
+ case TARGET_SO_REUSEPORT:
|
|
+ optname = SO_REUSEADDR;
|
|
+ break;
|
|
+
|
|
+ case TARGET_SO_KEEPALIVE:
|
|
+ optname = SO_KEEPALIVE;
|
|
+ break;
|
|
+
|
|
+ case TARGET_SO_DONTROUTE:
|
|
+ optname = SO_DONTROUTE;
|
|
+ break;
|
|
+
|
|
+ case TARGET_SO_LINGER:
|
|
+ optname = SO_LINGER;
|
|
+ break;
|
|
+
|
|
+ case TARGET_SO_BROADCAST:
|
|
+ optname = SO_BROADCAST;
|
|
+ break;
|
|
+
|
|
+ case TARGET_SO_OOBINLINE:
|
|
+ optname = SO_OOBINLINE;
|
|
+ break;
|
|
+
|
|
+ case TARGET_SO_SNDBUF:
|
|
+ optname = SO_SNDBUF;
|
|
+ break;
|
|
+
|
|
+ case TARGET_SO_RCVBUF:
|
|
+ optname = SO_RCVBUF;
|
|
+ break;
|
|
+
|
|
+ case TARGET_SO_SNDLOWAT:
|
|
+ optname = SO_RCVLOWAT;
|
|
+ break;
|
|
+
|
|
+ case TARGET_SO_RCVLOWAT:
|
|
+ optname = SO_RCVLOWAT;
|
|
+ break;
|
|
+
|
|
+ case TARGET_SO_SNDTIMEO:
|
|
+ optname = SO_SNDTIMEO;
|
|
+ break;
|
|
+
|
|
+ case TARGET_SO_RCVTIMEO:
|
|
+ optname = SO_RCVTIMEO;
|
|
+ break;
|
|
+
|
|
+ case TARGET_SO_ACCEPTFILTER:
|
|
+ goto unimplemented;
|
|
+
|
|
+ case TARGET_SO_NOSIGPIPE:
|
|
+ optname = SO_NOSIGPIPE;
|
|
+ break;
|
|
+
|
|
+ case TARGET_SO_TIMESTAMP:
|
|
+ optname = SO_TIMESTAMP;
|
|
+ break;
|
|
+
|
|
+ case TARGET_SO_BINTIME:
|
|
+ optname = SO_BINTIME;
|
|
+ break;
|
|
+
|
|
+ case TARGET_SO_ERROR:
|
|
+ optname = SO_ERROR;
|
|
+ break;
|
|
+
|
|
+ case TARGET_SO_SETFIB:
|
|
+ optname = SO_ERROR;
|
|
+ break;
|
|
+
|
|
+ case TARGET_SO_USER_COOKIE:
|
|
+ optname = SO_USER_COOKIE;
|
|
+ break;
|
|
+
|
|
+ default:
|
|
+ goto unimplemented;
|
|
+ }
|
|
+ if (optlen < sizeof(uint32_t))
|
|
+ return (-TARGET_EINVAL);
|
|
+ if (get_user_u32(val, optval_addr))
|
|
+ return (-TARGET_EFAULT);
|
|
+ ret = get_errno(setsockopt(sockfd, SOL_SOCKET, optname, &val,
|
|
+ sizeof(val)));
|
|
+ break;
|
|
+ default:
|
|
+unimplemented:
|
|
+ gemu_log("Unsupported setsockopt level=%d optname=%d\n",
|
|
+ level, optname);
|
|
+ ret = -TARGET_ENOPROTOOPT;
|
|
+ }
|
|
+
|
|
+ return (ret);
|
|
+}
|
|
+
|
|
+static inline abi_long
|
|
+target_to_host_sembuf(struct sembuf *host_sembuf, abi_ulong target_addr,
|
|
+ unsigned nsops)
|
|
+{
|
|
+ struct target_sembuf *target_sembuf;
|
|
+ int i;
|
|
+
|
|
+ target_sembuf = lock_user(VERIFY_READ, target_addr,
|
|
+ nsops * sizeof(struct target_sembuf), 1);
|
|
+ if (!target_sembuf)
|
|
+ return (-TARGET_EFAULT);
|
|
+
|
|
+ for(i=0; i<nsops; i++) {
|
|
+ __get_user(host_sembuf[i].sem_num, &target_sembuf[i].sem_num);
|
|
+ __get_user(host_sembuf[i].sem_op, &target_sembuf[i].sem_op);
|
|
+ __get_user(host_sembuf[i].sem_flg, &target_sembuf[i].sem_flg);
|
|
+ }
|
|
+
|
|
+ unlock_user(target_sembuf, target_addr, 0);
|
|
+
|
|
+ return (0);
|
|
+}
|
|
+
|
|
+static inline abi_long
|
|
+do_semop(int semid, abi_long ptr, unsigned nsops)
|
|
+{
|
|
+ struct sembuf sops[nsops];
|
|
+
|
|
+ if (target_to_host_sembuf(sops, ptr, nsops))
|
|
+ return (-TARGET_EFAULT);
|
|
+
|
|
+ return semop(semid, sops, nsops);
|
|
+}
|
|
+
|
|
+static inline abi_long
|
|
+target_to_host_semarray(int semid, unsigned short **host_array,
|
|
+ abi_ulong target_addr)
|
|
+{
|
|
+ int nsems;
|
|
+ unsigned short *array;
|
|
+ union semun semun;
|
|
+ struct semid_ds semid_ds;
|
|
+ int i, ret;
|
|
+
|
|
+ semun.buf = &semid_ds;
|
|
+ ret = semctl(semid, 0, IPC_STAT, semun);
|
|
+ if (ret == -1)
|
|
+ return (get_errno(ret));
|
|
+ nsems = semid_ds.sem_nsems;
|
|
+ *host_array = malloc(nsems * sizeof(unsigned short));
|
|
+ array = lock_user(VERIFY_READ, target_addr,
|
|
+ nsems*sizeof(unsigned short), 1);
|
|
+ if (!array)
|
|
+ return (-TARGET_EFAULT);
|
|
+ for(i=0; i<nsems; i++) {
|
|
+ __get_user((*host_array)[i], &array[i]);
|
|
+ }
|
|
+ unlock_user(array, target_addr, 0);
|
|
+
|
|
+ return (0);
|
|
+}
|
|
+
|
|
+static inline abi_long
|
|
+host_to_target_semarray(int semid, abi_ulong target_addr,
|
|
+ unsigned short **host_array)
|
|
+{
|
|
+ int nsems;
|
|
+ unsigned short *array;
|
|
+ union semun semun;
|
|
+ struct semid_ds semid_ds;
|
|
+ int i, ret;
|
|
+
|
|
+ semun.buf = &semid_ds;
|
|
+
|
|
+ ret = semctl(semid, 0, IPC_STAT, semun);
|
|
+ if (ret == -1)
|
|
+ return get_errno(ret);
|
|
+
|
|
+ nsems = semid_ds.sem_nsems;
|
|
+
|
|
+ array = lock_user(VERIFY_WRITE, target_addr,
|
|
+ nsems*sizeof(unsigned short), 0);
|
|
+ if (!array)
|
|
+ return (-TARGET_EFAULT);
|
|
+
|
|
+ for(i=0; i<nsems; i++) {
|
|
+ __put_user((*host_array)[i], &array[i]);
|
|
+ }
|
|
+ free(*host_array);
|
|
+ unlock_user(array, target_addr, 1);
|
|
+
|
|
+ return (0);
|
|
+}
|
|
+
|
|
+static inline abi_long
|
|
+target_to_host_ipc_perm(struct ipc_perm *host_ip, abi_ulong target_addr)
|
|
+{
|
|
+ struct target_ipc_perm *target_ip;
|
|
+ struct target_semid_ds *target_sd;
|
|
+
|
|
+ if (!lock_user_struct(VERIFY_READ, target_sd, target_addr, 1))
|
|
+ return (-TARGET_EFAULT);
|
|
+ target_ip = &(target_sd->sem_perm);
|
|
+ host_ip->cuid = tswapal(target_ip->cuid);
|
|
+ host_ip->cgid = tswapal(target_ip->cgid);
|
|
+ host_ip->uid = tswapal(target_ip->uid);
|
|
+ host_ip->gid = tswapal(target_ip->gid);
|
|
+ host_ip->mode = tswap16(target_ip->mode);
|
|
+ host_ip->seq = tswap16(target_ip->seq);
|
|
+ host_ip->key = tswapal(target_ip->key);
|
|
+ unlock_user_struct(target_sd, target_addr, 0);
|
|
+
|
|
+ return (0);
|
|
+}
|
|
+
|
|
+static inline abi_long
|
|
+host_to_target_ipc_perm(abi_ulong target_addr, struct ipc_perm *host_ip)
|
|
+{
|
|
+ struct target_ipc_perm *target_ip;
|
|
+ struct target_semid_ds *target_sd;
|
|
+ if (!lock_user_struct(VERIFY_WRITE, target_sd, target_addr, 0))
|
|
+ return (-TARGET_EFAULT);
|
|
+ target_ip = &(target_sd->sem_perm);
|
|
+ target_ip->cuid = tswapal(host_ip->cuid);
|
|
+ target_ip->cgid = tswapal(host_ip->cgid);
|
|
+ target_ip->uid = tswapal(host_ip->uid);
|
|
+ target_ip->gid = tswapal(host_ip->gid);
|
|
+ target_ip->mode = tswap16(host_ip->mode);
|
|
+ target_ip->seq = tswap16(host_ip->seq);
|
|
+ target_ip->key = tswapal(host_ip->key);
|
|
+ unlock_user_struct(target_sd, target_addr, 1);
|
|
+ return (0);
|
|
+}
|
|
+
|
|
+static inline abi_long
|
|
+target_to_host_semid_ds(struct semid_ds *host_sd, abi_ulong target_addr)
|
|
+{
|
|
+ struct target_semid_ds *target_sd;
|
|
+
|
|
+ if (!lock_user_struct(VERIFY_READ, target_sd, target_addr, 1))
|
|
+ return (-TARGET_EFAULT);
|
|
+ if (target_to_host_ipc_perm(&(host_sd->sem_perm), target_addr))
|
|
+ return (-TARGET_EFAULT);
|
|
+ /* sem_base is not used by kernel for IPC_STAT/IPC_SET */
|
|
+ host_sd->sem_base = NULL;
|
|
+ host_sd->sem_nsems = tswapal(target_sd->sem_nsems);
|
|
+ host_sd->sem_otime = tswapal(target_sd->sem_otime);
|
|
+ host_sd->sem_ctime = tswapal(target_sd->sem_ctime);
|
|
+ unlock_user_struct(target_sd, target_addr, 0);
|
|
+ return (0);
|
|
+}
|
|
+
|
|
+static inline abi_long
|
|
+host_to_target_semid_ds(abi_ulong target_addr, struct semid_ds *host_sd)
|
|
+{
|
|
+ struct target_semid_ds *target_sd;
|
|
+
|
|
+ if (!lock_user_struct(VERIFY_WRITE, target_sd, target_addr, 0))
|
|
+ return (-TARGET_EFAULT);
|
|
+ if (host_to_target_ipc_perm(target_addr,&(host_sd->sem_perm)))
|
|
+ return (-TARGET_EFAULT);
|
|
+ /* sem_base is not used by kernel for IPC_STAT/IPC_SET */
|
|
+ target_sd->sem_nsems = tswapal(host_sd->sem_nsems);
|
|
+ target_sd->sem_otime = tswapal(host_sd->sem_otime);
|
|
+ target_sd->sem_ctime = tswapal(host_sd->sem_ctime);
|
|
+ unlock_user_struct(target_sd, target_addr, 1);
|
|
+
|
|
+ return (0);
|
|
+}
|
|
+
|
|
+static inline abi_long
|
|
+do_semctl(int semid, int semnum, int cmd, union target_semun target_su)
|
|
+{
|
|
+ union semun arg;
|
|
+ struct semid_ds dsarg;
|
|
+ unsigned short *array = NULL;
|
|
+ abi_long ret = -TARGET_EINVAL;
|
|
+ abi_long err;
|
|
+
|
|
+ cmd &= 0xff;
|
|
+
|
|
+ switch( cmd ) {
|
|
+ case GETVAL:
|
|
+ case SETVAL:
|
|
+ arg.val = tswap32(target_su.val);
|
|
+ ret = get_errno(semctl(semid, semnum, cmd, arg));
|
|
+ target_su.val = tswap32(arg.val);
|
|
+ break;
|
|
+
|
|
+ case GETALL:
|
|
+ case SETALL:
|
|
+ err = target_to_host_semarray(semid, &array, target_su.array);
|
|
+ if (err)
|
|
+ return (err);
|
|
+ arg.array = array;
|
|
+ ret = get_errno(semctl(semid, semnum, cmd, arg));
|
|
+ err = host_to_target_semarray(semid, target_su.array, &array);
|
|
+ if (err)
|
|
+ return (err);
|
|
+ break;
|
|
+
|
|
+ case IPC_STAT:
|
|
+ case IPC_SET:
|
|
+ err = target_to_host_semid_ds(&dsarg, target_su.buf);
|
|
+ if (err)
|
|
+ return (err);
|
|
+ arg.buf = &dsarg;
|
|
+ ret = get_errno(semctl(semid, semnum, cmd, arg));
|
|
+ err = host_to_target_semid_ds(target_su.buf, &dsarg);
|
|
+ if (err)
|
|
+ return (err);
|
|
+ break;
|
|
+
|
|
+ case IPC_RMID:
|
|
+ case GETPID:
|
|
+ case GETNCNT:
|
|
+ case GETZCNT:
|
|
+ ret = get_errno(semctl(semid, semnum, cmd, NULL));
|
|
+ break;
|
|
+
|
|
+ default:
|
|
+ ret = -TARGET_EINVAL;
|
|
+ break;
|
|
+ }
|
|
+ return (ret);
|
|
+}
|
|
+
|
|
+#define N_SHM_REGIONS 32
|
|
+
|
|
+static struct shm_regions {
|
|
+ abi_long start;
|
|
+ abi_long size;
|
|
+} shm_regions[N_SHM_REGIONS];
|
|
+
|
|
+static inline abi_ulong
|
|
+do_shmat(int shmid, abi_ulong shmaddr, int shmflg)
|
|
+{
|
|
+ abi_long raddr;
|
|
+ void *host_raddr;
|
|
+ struct shmid_ds shm_info;
|
|
+ int i,ret;
|
|
+
|
|
+ /* Find out the length of the shared memory segment. */
|
|
+ ret = get_errno(shmctl(shmid, IPC_STAT, &shm_info));
|
|
+ if (is_error(ret)) {
|
|
+ /* Can't get the length */
|
|
+ return (ret);
|
|
+ }
|
|
+
|
|
+ mmap_lock();
|
|
+
|
|
+ if (shmaddr) {
|
|
+ host_raddr = shmat(shmid, (void *)g2h(shmaddr), shmflg);
|
|
+ } else {
|
|
+ abi_ulong mmap_start;
|
|
+
|
|
+ mmap_start = mmap_find_vma(0, shm_info.shm_segsz);
|
|
+
|
|
+ if (mmap_start == -1) {
|
|
+ errno = ENOMEM;
|
|
+ host_raddr = (void *)-1;
|
|
+ } else {
|
|
+ host_raddr = shmat(shmid, g2h(mmap_start),
|
|
+ shmflg /* | SHM_REMAP */);
|
|
+ }
|
|
+ }
|
|
+
|
|
+ if (host_raddr == (void *)-1) {
|
|
+ mmap_unlock();
|
|
+ return get_errno((long)host_raddr);
|
|
+ }
|
|
+ raddr=h2g((unsigned long)host_raddr);
|
|
+
|
|
+ page_set_flags(raddr, raddr + shm_info.shm_segsz,
|
|
+ PAGE_VALID | PAGE_READ | ((shmflg & SHM_RDONLY)? 0 : PAGE_WRITE));
|
|
+
|
|
+ for (i = 0; i < N_SHM_REGIONS; i++) {
|
|
+ if (shm_regions[i].start == 0) {
|
|
+ shm_regions[i].start = raddr;
|
|
+ shm_regions[i].size = shm_info.shm_segsz;
|
|
+ break;
|
|
+ }
|
|
+ }
|
|
+
|
|
+ mmap_unlock();
|
|
+ return (raddr);
|
|
+}
|
|
+
|
|
+static inline abi_long
|
|
+do_shmdt(abi_ulong shmaddr)
|
|
+{
|
|
+ int i;
|
|
+
|
|
+ for (i = 0; i < N_SHM_REGIONS; ++i) {
|
|
+ if (shm_regions[i].start == shmaddr) {
|
|
+ shm_regions[i].start = 0;
|
|
+ page_set_flags(shmaddr,
|
|
+ shmaddr + shm_regions[i].size, 0);
|
|
+ break;
|
|
+ }
|
|
+ }
|
|
+
|
|
+ return ( get_errno(shmdt(g2h(shmaddr))) );
|
|
+}
|
|
+
|
|
+static inline abi_long
|
|
+target_to_host_shmid_ds(struct shmid_ds *host_sd, abi_ulong target_addr)
|
|
+{
|
|
+ struct target_shmid_ds *target_sd;
|
|
+
|
|
+ if (!lock_user_struct(VERIFY_READ, target_sd, target_addr, 1))
|
|
+ return (-TARGET_EFAULT);
|
|
+ if (target_to_host_ipc_perm(&(host_sd->shm_perm), target_addr))
|
|
+ return (-TARGET_EFAULT);
|
|
+ __get_user(host_sd->shm_segsz, &target_sd->shm_segsz);
|
|
+ __get_user(host_sd->shm_lpid, &target_sd->shm_lpid);
|
|
+ __get_user(host_sd->shm_cpid, &target_sd->shm_cpid);
|
|
+ __get_user(host_sd->shm_nattch, &target_sd->shm_nattch);
|
|
+ __get_user(host_sd->shm_atime, &target_sd->shm_atime);
|
|
+ __get_user(host_sd->shm_dtime, &target_sd->shm_dtime);
|
|
+ __get_user(host_sd->shm_ctime, &target_sd->shm_ctime);
|
|
+ unlock_user_struct(target_sd, target_addr, 0);
|
|
+ return (0);
|
|
+}
|
|
+
|
|
+static inline abi_long
|
|
+host_to_target_shmid_ds(abi_ulong target_addr, struct shmid_ds *host_sd)
|
|
+{
|
|
+ struct target_shmid_ds *target_sd;
|
|
+
|
|
+ if (!lock_user_struct(VERIFY_WRITE, target_sd, target_addr, 0))
|
|
+ return (-TARGET_EFAULT);
|
|
+ if (host_to_target_ipc_perm(target_addr, &(host_sd->shm_perm)))
|
|
+ return (-TARGET_EFAULT);
|
|
+ __put_user(host_sd->shm_segsz, &target_sd->shm_segsz);
|
|
+ __put_user(host_sd->shm_lpid, &target_sd->shm_lpid);
|
|
+ __put_user(host_sd->shm_cpid, &target_sd->shm_cpid);
|
|
+ __put_user(host_sd->shm_nattch, &target_sd->shm_nattch);
|
|
+ __put_user(host_sd->shm_atime, &target_sd->shm_atime);
|
|
+ __put_user(host_sd->shm_dtime, &target_sd->shm_dtime);
|
|
+ __put_user(host_sd->shm_ctime, &target_sd->shm_ctime);
|
|
+ unlock_user_struct(target_sd, target_addr, 1);
|
|
+ return (0);
|
|
+}
|
|
+
|
|
+static inline abi_long
|
|
+do_shmctl(int shmid, int cmd, abi_long buff)
|
|
+{
|
|
+ struct shmid_ds dsarg;
|
|
+ abi_long ret = -TARGET_EINVAL;
|
|
+
|
|
+ cmd &= 0xff;
|
|
+
|
|
+ switch(cmd) {
|
|
+ case IPC_STAT:
|
|
+ case IPC_SET:
|
|
+ if (target_to_host_shmid_ds(&dsarg, buff))
|
|
+ return (-TARGET_EFAULT);
|
|
+ ret = get_errno(shmctl(shmid, cmd, &dsarg));
|
|
+ if (host_to_target_shmid_ds(buff, &dsarg))
|
|
+ return (-TARGET_EFAULT);
|
|
+ break;
|
|
+
|
|
+ case IPC_RMID:
|
|
+ ret = get_errno(shmctl(shmid, cmd, NULL));
|
|
+ break;
|
|
+
|
|
+ default:
|
|
+ ret = -TARGET_EINVAL;
|
|
+ break;
|
|
+ }
|
|
+
|
|
+ return (ret);
|
|
+}
|
|
+
|
|
+static inline abi_long
|
|
+target_to_host_msqid_ds(struct msqid_ds *host_md, abi_ulong target_addr)
|
|
+{
|
|
+ struct target_msqid_ds *target_md;
|
|
+
|
|
+ if (!lock_user_struct(VERIFY_READ, target_md, target_addr, 1))
|
|
+ return (-TARGET_EFAULT);
|
|
+ if (target_to_host_ipc_perm(&(host_md->msg_perm),target_addr))
|
|
+ return (-TARGET_EFAULT);
|
|
+
|
|
+ /* msg_first and msg_last are not used by IPC_SET/IPC_STAT in kernel. */
|
|
+ host_md->msg_first = host_md->msg_last = NULL;
|
|
+
|
|
+ host_md->msg_cbytes = tswapal(target_md->msg_cbytes);
|
|
+ host_md->msg_qnum = tswapal(target_md->msg_qnum);
|
|
+ host_md->msg_qbytes = tswapal(target_md->msg_qbytes);
|
|
+ host_md->msg_lspid = tswapal(target_md->msg_lspid);
|
|
+ host_md->msg_lrpid = tswapal(target_md->msg_lrpid);
|
|
+ host_md->msg_stime = tswapal(target_md->msg_stime);
|
|
+ host_md->msg_rtime = tswapal(target_md->msg_rtime);
|
|
+ host_md->msg_ctime = tswapal(target_md->msg_ctime);
|
|
+ unlock_user_struct(target_md, target_addr, 0);
|
|
+
|
|
+ return (0);
|
|
+}
|
|
+
|
|
+static inline abi_long
|
|
+host_to_target_msqid_ds(abi_ulong target_addr, struct msqid_ds *host_md)
|
|
+{
|
|
+ struct target_msqid_ds *target_md;
|
|
+
|
|
+ if (!lock_user_struct(VERIFY_WRITE, target_md, target_addr, 0))
|
|
+ return (-TARGET_EFAULT);
|
|
+ if (host_to_target_ipc_perm(target_addr,&(host_md->msg_perm)))
|
|
+ return (-TARGET_EFAULT);
|
|
+
|
|
+ /* msg_first and msg_last are not used by IPC_SET/IPC_STAT in kernel. */
|
|
+ target_md->msg_cbytes = tswapal(host_md->msg_cbytes);
|
|
+ target_md->msg_qnum = tswapal(host_md->msg_qnum);
|
|
+ target_md->msg_qbytes = tswapal(host_md->msg_qbytes);
|
|
+ target_md->msg_lspid = tswapal(host_md->msg_lspid);
|
|
+ target_md->msg_lrpid = tswapal(host_md->msg_lrpid);
|
|
+ target_md->msg_stime = tswapal(host_md->msg_stime);
|
|
+ target_md->msg_rtime = tswapal(host_md->msg_rtime);
|
|
+ target_md->msg_ctime = tswapal(host_md->msg_ctime);
|
|
+ unlock_user_struct(target_md, target_addr, 1);
|
|
+
|
|
+ return (0);
|
|
+}
|
|
+
|
|
+static inline abi_long
|
|
+do_msgctl(int msgid, int cmd, abi_long ptr)
|
|
+{
|
|
+ struct msqid_ds dsarg;
|
|
+ abi_long ret = -TARGET_EINVAL;
|
|
+
|
|
+ cmd &= 0xff;
|
|
+
|
|
+ switch (cmd) {
|
|
+ case IPC_STAT:
|
|
+ case IPC_SET:
|
|
+ if (target_to_host_msqid_ds(&dsarg,ptr))
|
|
+ return -TARGET_EFAULT;
|
|
+ ret = get_errno(msgctl(msgid, cmd, &dsarg));
|
|
+ if (host_to_target_msqid_ds(ptr,&dsarg))
|
|
+ return -TARGET_EFAULT;
|
|
+ break;
|
|
+
|
|
+ case IPC_RMID:
|
|
+ ret = get_errno(msgctl(msgid, cmd, NULL));
|
|
+ break;
|
|
+
|
|
+ default:
|
|
+ ret = -TARGET_EINVAL;
|
|
+ break;
|
|
+ }
|
|
+ return (ret);
|
|
+}
|
|
+
|
|
+static inline abi_long
|
|
+do_msgsnd(int msqid, abi_long msgp, unsigned int msgsz, int msgflg)
|
|
+{
|
|
+ struct target_msgbuf *target_mb;
|
|
+ struct mymsg *host_mb;
|
|
+ abi_long ret = 0;
|
|
+
|
|
+ if (!lock_user_struct(VERIFY_READ, target_mb, msgp, 0))
|
|
+ return (-TARGET_EFAULT);
|
|
+
|
|
+ host_mb = malloc(msgsz+sizeof(long));
|
|
+ host_mb->mtype = (abi_long) tswapal(target_mb->mtype);
|
|
+ memcpy(host_mb->mtext, target_mb->mtext, msgsz);
|
|
+ ret = get_errno(msgsnd(msqid, host_mb, msgsz, msgflg));
|
|
+ free(host_mb);
|
|
+ unlock_user_struct(target_mb, msgp, 0);
|
|
+
|
|
+ return (ret);
|
|
+}
|
|
+
|
|
+static inline abi_long
|
|
+do_msgrcv(int msqid, abi_long msgp, unsigned int msgsz, abi_long msgtyp,
|
|
+ int msgflg)
|
|
+{
|
|
+ struct target_msgbuf *target_mb;
|
|
+ char *target_mtext;
|
|
+ struct mymsg *host_mb;
|
|
+ abi_long ret = 0;
|
|
+
|
|
+ if (!lock_user_struct(VERIFY_WRITE, target_mb, msgp, 0))
|
|
+ return (-TARGET_EFAULT);
|
|
+
|
|
+ host_mb = g_malloc(msgsz+sizeof(long));
|
|
+ ret = get_errno(msgrcv(msqid, host_mb, msgsz, tswapal(msgtyp), msgflg));
|
|
+ if (ret > 0) {
|
|
+ abi_ulong target_mtext_addr = msgp + sizeof(abi_ulong);
|
|
+ target_mtext = lock_user(VERIFY_WRITE, target_mtext_addr,
|
|
+ ret, 0);
|
|
+ if (!target_mtext) {
|
|
+ ret = -TARGET_EFAULT;
|
|
+ goto end;
|
|
+ }
|
|
+ memcpy(target_mb->mtext, host_mb->mtext, ret);
|
|
+ unlock_user(target_mtext, target_mtext_addr, ret);
|
|
+ }
|
|
+ target_mb->mtype = tswapal(host_mb->mtype);
|
|
+end:
|
|
+ if (target_mb)
|
|
+ unlock_user_struct(target_mb, msgp, 1);
|
|
+ g_free(host_mb);
|
|
+ return (ret);
|
|
+}
|
|
+
|
|
+static void
|
|
+set_second_rval(CPUArchState *env, abi_ulong retval2)
|
|
+{
|
|
+#if defined(TARGET_ALPHA)
|
|
+ ((CPUAlphaState *)env)->ir[IR_A4] = retval2;
|
|
+#elif defined(TARGET_ARM)
|
|
+ ((CPUARMState *)env)->regs[1] = retval2;
|
|
+#elif defined(TARGET_MIPS)
|
|
+ ((CPUMIPSState*)env)->active_tc.gpr[3] = retval2;
|
|
+#elif defined(TARGET_SH4)
|
|
+ ((CPUSH4State*)env)->gregs[1] = retval2;
|
|
+#elif defined(TARGET_X86_64) || defined(TARGET_I386)
|
|
+ ((CPUX86State*)env)->regs[R_EDX] = retval2;
|
|
+#elif defined(TARGET_SPARC64) || defined(TARGET_SPARC)
|
|
+ ((CPUSPARCState*)env)->regwptr[1] = retval2;
|
|
+#else
|
|
+#warning Arch not supported for returning multiple values from syscall.
|
|
+#endif
|
|
+}
|
|
+
|
|
+/*
|
|
+ * do_fock() must return host values and target errnos (unlike most do_*()
|
|
+ * functions.
|
|
+ */
|
|
+static int
|
|
+do_fork(CPUArchState *env, int num, int flags, int *fdp)
|
|
+{
|
|
+ int ret, fd;
|
|
+ abi_ulong child_flag = 0;
|
|
+
|
|
+ fork_start();
|
|
+ switch(num) {
|
|
+ case TARGET_FREEBSD_NR_fork:
|
|
+ case TARGET_FREEBSD_NR_vfork:
|
|
+ ret = fork();
|
|
+ break;
|
|
+
|
|
+ case TARGET_FREEBSD_NR_rfork:
|
|
+ ret = rfork(flags);
|
|
+ break;
|
|
+
|
|
+ case TARGET_FREEBSD_NR_pdfork:
|
|
+ ret = pdfork(&fd, flags);
|
|
+ break;
|
|
+
|
|
+ default:
|
|
+ ret = -TARGET_ENOSYS;
|
|
+ break;
|
|
+ }
|
|
+ if (0 == ret) {
|
|
+ /* Child */
|
|
+ child_flag = 1;
|
|
+ cpu_clone_regs(env, 0);
|
|
+ } else {
|
|
+ /* Parent */
|
|
+ fork_end(0);
|
|
+ }
|
|
+ if (fdp != NULL)
|
|
+ *fdp = fd;
|
|
+
|
|
+ /*
|
|
+ * The fork() syscall sets a child flag in 2nd return value:
|
|
+ * 0 for parent process, 1 for child process
|
|
+ */
|
|
+ set_second_rval(env, child_flag);
|
|
+
|
|
+ return (ret);
|
|
+}
|
|
+
|
|
+/* do_syscall() should always have a single exit point at the end so
|
|
+ that actions, such as logging of syscall results, can be performed.
|
|
+ All errnos that do_syscall() returns must be -TARGET_<errcode>. */
|
|
+abi_long do_freebsd_syscall(void *cpu_env, int num, abi_long arg1,
|
|
+ abi_long arg2, abi_long arg3, abi_long arg4,
|
|
+ abi_long arg5, abi_long arg6, abi_long arg7,
|
|
+ abi_long arg8)
|
|
+{
|
|
+ abi_long ret;
|
|
+ void *p;
|
|
+ struct stat st;
|
|
+
|
|
+#ifdef DEBUG
|
|
+ gemu_log("freebsd syscall %d\n", num);
|
|
+#endif
|
|
+ if(do_strace)
|
|
+ print_freebsd_syscall(num, arg1, arg2, arg3, arg4, arg5, arg6);
|
|
+
|
|
+ switch(num) {
|
|
+ case TARGET_FREEBSD_NR_exit:
|
|
+#ifdef TARGET_GPROF
|
|
+ _mcleanup();
|
|
+#endif
|
|
+ gdb_exit(cpu_env, arg1);
|
|
+ /* XXX: should free thread stack and CPU env */
|
|
+ _exit(arg1);
|
|
+ ret = 0; /* avoid warning */
|
|
+ break;
|
|
+ case TARGET_FREEBSD_NR_read:
|
|
+ if (!(p = lock_user(VERIFY_WRITE, arg2, arg3, 0)))
|
|
+ goto efault;
|
|
+ ret = get_errno(read(arg1, p, arg3));
|
|
+ unlock_user(p, arg2, ret);
|
|
+ break;
|
|
+
|
|
+ case TARGET_FREEBSD_NR_readv:
|
|
+ {
|
|
+ int count = arg3;
|
|
+ struct iovec *vec;
|
|
+
|
|
+ vec = alloca(count * sizeof(struct iovec));
|
|
+ if (lock_iovec(VERIFY_WRITE, vec, arg2, count, 0) < 0)
|
|
+ goto efault;
|
|
+ ret = get_errno(readv(arg1, vec, count));
|
|
+ unlock_iovec(vec, arg2, count, 1);
|
|
+ }
|
|
+ break;
|
|
+
|
|
+ case TARGET_FREEBSD_NR_pread:
|
|
+ if (!(p = lock_user(VERIFY_WRITE, arg2, arg3, 0)))
|
|
+ goto efault;
|
|
+ ret = get_errno(pread(arg1, p, arg3, target_offset64(arg4, arg5)));
|
|
+ unlock_user(p, arg2, ret);
|
|
+ break;
|
|
+
|
|
+ case TARGET_FREEBSD_NR_preadv:
|
|
+ {
|
|
+ int count = arg3;
|
|
+ struct iovec *vec;
|
|
+
|
|
+ vec = alloca(count * sizeof(struct iovec));
|
|
+ if (lock_iovec(VERIFY_WRITE, vec, arg2, count, 0) < 0)
|
|
+ goto efault;
|
|
+ ret = get_errno(preadv(arg1, vec, count,
|
|
+ target_offset64(arg4, arg5)));
|
|
+ unlock_iovec(vec, arg2, count, 1);
|
|
+ }
|
|
+ break;
|
|
+
|
|
+ case TARGET_FREEBSD_NR_write:
|
|
+ if (!(p = lock_user(VERIFY_READ, arg2, arg3, 1)))
|
|
+ goto efault;
|
|
+ ret = get_errno(write(arg1, p, arg3));
|
|
+ unlock_user(p, arg2, 0);
|
|
+ break;
|
|
+
|
|
+ case TARGET_FREEBSD_NR_writev:
|
|
+ {
|
|
+ int count = arg3;
|
|
+ struct iovec *vec;
|
|
+
|
|
+ vec = alloca(count * sizeof(struct iovec));
|
|
+ if (lock_iovec(VERIFY_READ, vec, arg2, count, 1) < 0)
|
|
+ goto efault;
|
|
+ ret = get_errno(writev(arg1, vec, count));
|
|
+ unlock_iovec(vec, arg2, count, 0);
|
|
+ }
|
|
+ break;
|
|
+
|
|
+ case TARGET_FREEBSD_NR_pwrite:
|
|
+ if (!(p = lock_user(VERIFY_READ, arg2, arg3, 1)))
|
|
+ goto efault;
|
|
+ ret = get_errno(pwrite(arg1, p, arg3, target_offset64(arg4, arg5)));
|
|
+ unlock_user(p, arg2, 0);
|
|
+ break;
|
|
+
|
|
+ case TARGET_FREEBSD_NR_pwritev:
|
|
+ {
|
|
+ int count = arg3;
|
|
+ struct iovec *vec;
|
|
+
|
|
+ vec = alloca(count * sizeof(struct iovec));
|
|
+ if (lock_iovec(VERIFY_READ, vec, arg2, count, 1) < 0)
|
|
+ goto efault;
|
|
+ ret = get_errno(pwritev(arg1, vec, count,
|
|
+ target_offset64(arg4, arg5)));
|
|
+ unlock_iovec(vec, arg2, count, 0);
|
|
+ }
|
|
+ break;
|
|
+
|
|
+ case TARGET_FREEBSD_NR_open:
|
|
+ if (!(p = lock_user_string(arg1)))
|
|
+ goto efault;
|
|
+ ret = get_errno(open(path(p),
|
|
+ target_to_host_bitmask(arg2, fcntl_flags_tbl),
|
|
+ arg3));
|
|
+ unlock_user(p, arg1, 0);
|
|
+ break;
|
|
+
|
|
+ case TARGET_FREEBSD_NR_openat:
|
|
+ if (!(p = lock_user_string(arg2)))
|
|
+ goto efault;
|
|
+ ret = get_errno(openat(arg1, path(p),
|
|
+ target_to_host_bitmask(arg3, fcntl_flags_tbl),
|
|
+ arg4));
|
|
+ unlock_user(p, arg2, 0);
|
|
+ break;
|
|
+
|
|
+ case TARGET_FREEBSD_NR_close:
|
|
+ ret = get_errno(close(arg1));
|
|
+ break;
|
|
+
|
|
+ case TARGET_FREEBSD_NR_closefrom:
|
|
+ ret = 0;
|
|
+ closefrom(arg1);
|
|
+ break;
|
|
+
|
|
+#ifdef TARGET_FREEBSD_NR_creat
|
|
+ case TARGET_FREEBSD_NR_creat:
|
|
+ if (!(p = lock_user_string(arg1)))
|
|
+ goto efault;
|
|
+ ret = get_errno(creat(p, arg2));
|
|
+ unlock_user(p, arg1, 0);
|
|
+ break;
|
|
+#endif
|
|
+
|
|
+ case TARGET_FREEBSD_NR_mmap:
|
|
+ ret = get_errno(target_mmap(arg1, arg2, arg3,
|
|
+ target_to_host_bitmask(arg4, mmap_flags_tbl),
|
|
+ arg5,
|
|
+ arg6));
|
|
+ break;
|
|
+
|
|
+ case TARGET_FREEBSD_NR_munmap:
|
|
+ ret = get_errno(target_munmap(arg1, arg2));
|
|
+ break;
|
|
+
|
|
+ case TARGET_FREEBSD_NR_mprotect:
|
|
+ ret = get_errno(target_mprotect(arg1, arg2, arg3));
|
|
+ break;
|
|
+
|
|
+ case TARGET_FREEBSD_NR_msync:
|
|
+ ret = get_errno(msync(g2h(arg1), arg2, arg3));
|
|
+ break;
|
|
+
|
|
+ case TARGET_FREEBSD_NR_mlock:
|
|
+ ret = get_errno(mlock(g2h(arg1), arg2));
|
|
+ break;
|
|
+
|
|
+ case TARGET_FREEBSD_NR_munlock:
|
|
+ ret = get_errno(munlock(g2h(arg1), arg2));
|
|
+ break;
|
|
+
|
|
+ case TARGET_FREEBSD_NR_mlockall:
|
|
+ ret = get_errno(mlockall(arg1));
|
|
+ break;
|
|
+
|
|
+ case TARGET_FREEBSD_NR_munlockall:
|
|
+ ret = get_errno(munlockall());
|
|
+ break;
|
|
+
|
|
+ case TARGET_FREEBSD_NR_madvise:
|
|
+ /*
|
|
+ * A straight passthrough may not be safe because qemu sometimes
|
|
+ * turns private file-backed mapping into anonymous mappings. This
|
|
+ * will break MADV_DONTNEED. This is a hint, so ignoring and returing
|
|
+ * success is ok.
|
|
+ */
|
|
+ ret = get_errno(0);
|
|
+ break;
|
|
+
|
|
+ case TARGET_FREEBSD_NR_break:
|
|
+ ret = do_obreak(arg1);
|
|
+ break;
|
|
+#ifdef __FreeBSD__
|
|
+ case TARGET_FREEBSD_NR___sysctl:
|
|
+ ret = do_freebsd_sysctl(arg1, arg2, arg3, arg4, arg5, arg6);
|
|
+ break;
|
|
+#endif
|
|
+ case TARGET_FREEBSD_NR_sysarch:
|
|
+ ret = do_freebsd_sysarch(cpu_env, arg1, arg2);
|
|
+ break;
|
|
+ case TARGET_FREEBSD_NR_syscall:
|
|
+ case TARGET_FREEBSD_NR___syscall:
|
|
+ ret = do_freebsd_syscall(cpu_env,arg1 & 0xffff,arg2,arg3,arg4,arg5,arg6,arg7,arg8,0);
|
|
+ break;
|
|
+
|
|
+ case TARGET_FREEBSD_NR_stat:
|
|
+ if (!(p = lock_user_string(arg1)))
|
|
+ goto efault;
|
|
+ ret = get_errno(stat(path(p), &st));
|
|
+ unlock_user(p, arg1, 0);
|
|
+ goto do_stat;
|
|
+
|
|
+ case TARGET_FREEBSD_NR_lstat:
|
|
+ if (!(p = lock_user_string(arg1)))
|
|
+ goto efault;
|
|
+ ret = get_errno(lstat(path(p), &st));
|
|
+ unlock_user(p, arg1, 0);
|
|
+ goto do_stat;
|
|
+
|
|
+ case TARGET_FREEBSD_NR_nstat:
|
|
+ case TARGET_FREEBSD_NR_nfstat:
|
|
+ case TARGET_FREEBSD_NR_nlstat:
|
|
+ ret = unimplemented(num);
|
|
+ break;
|
|
+
|
|
+ case TARGET_FREEBSD_NR_fstat:
|
|
+ {
|
|
+ ret = get_errno(fstat(arg1, &st));
|
|
+
|
|
+do_stat:
|
|
+ if (!is_error(ret)) {
|
|
+ struct target_freebsd_stat *target_st;
|
|
+
|
|
+ if (!lock_user_struct(VERIFY_WRITE, target_st, arg2, 0))
|
|
+ goto efault;
|
|
+ memset(target_st, 0, sizeof(*target_st));
|
|
+ __put_user(st.st_dev, &target_st->st_dev);
|
|
+ __put_user(st.st_ino, &target_st->st_ino);
|
|
+ __put_user(st.st_mode, &target_st->st_mode);
|
|
+ __put_user(st.st_nlink, &target_st->st_nlink);
|
|
+ __put_user(st.st_uid, &target_st->st_uid);
|
|
+ __put_user(st.st_gid, &target_st->st_gid);
|
|
+ __put_user(st.st_rdev, &target_st->st_rdev);
|
|
+ __put_user(st.st_atim.tv_sec, &target_st->st_atim.tv_sec);
|
|
+ __put_user(st.st_atim.tv_nsec, &target_st->st_atim.tv_nsec);
|
|
+ __put_user(st.st_mtim.tv_sec, &target_st->st_mtim.tv_sec);
|
|
+ __put_user(st.st_mtim.tv_nsec, &target_st->st_mtim.tv_nsec);
|
|
+ __put_user(st.st_ctim.tv_sec, &target_st->st_ctim.tv_sec);
|
|
+ __put_user(st.st_ctim.tv_nsec, &target_st->st_ctim.tv_nsec);
|
|
+ __put_user(st.st_size, &target_st->st_size);
|
|
+ __put_user(st.st_blocks, &target_st->st_blocks);
|
|
+ __put_user(st.st_blksize, &target_st->st_blksize);
|
|
+ __put_user(st.st_flags, &target_st->st_flags);
|
|
+ __put_user(st.st_gen, &target_st->st_gen);
|
|
+ /* st_lspare not used */
|
|
+ __put_user(st.st_birthtim.tv_sec,
|
|
+ &target_st->st_birthtim.tv_sec);
|
|
+ __put_user(st.st_birthtim.tv_nsec,
|
|
+ &target_st->st_birthtim.tv_nsec);
|
|
+ unlock_user_struct(target_st, arg2, 1);
|
|
+ }
|
|
+
|
|
+ }
|
|
+ break;
|
|
+
|
|
+ case TARGET_FREEBSD_NR_nanosleep:
|
|
+ {
|
|
+ struct timespec req, rem;
|
|
+
|
|
+ target_to_host_timespec(&req, arg1);
|
|
+ ret = get_errno(nanosleep(&req, &rem));
|
|
+ if (is_error(ret) && arg2)
|
|
+ host_to_target_timespec(arg2, &rem);
|
|
+ }
|
|
+ break;
|
|
+
|
|
+ case TARGET_FREEBSD_NR_clock_gettime:
|
|
+ {
|
|
+ struct timespec ts;
|
|
+
|
|
+ ret = get_errno(clock_gettime(arg1, &ts));
|
|
+ if (!is_error(ret)) {
|
|
+ if (host_to_target_timespec(arg2, &ts))
|
|
+ goto efault;
|
|
+ }
|
|
+ }
|
|
+ break;
|
|
+
|
|
+ case TARGET_FREEBSD_NR_clock_getres:
|
|
+ {
|
|
+ struct timespec ts;
|
|
+
|
|
+ ret = get_errno(clock_getres(arg1, &ts));
|
|
+ if (!is_error(ret)) {
|
|
+ if (host_to_target_timespec(arg2, &ts))
|
|
+ goto efault;
|
|
+ }
|
|
+ }
|
|
+ break;
|
|
+
|
|
+ case TARGET_FREEBSD_NR_clock_settime:
|
|
+ {
|
|
+ struct timespec ts;
|
|
+
|
|
+ if (target_to_host_timespec(&ts, arg2) != 0)
|
|
+ goto efault;
|
|
+ ret = get_errno(clock_settime(arg1, &ts));
|
|
+ }
|
|
+ break;
|
|
+
|
|
+ case TARGET_FREEBSD_NR_gettimeofday:
|
|
+ {
|
|
+ struct timeval tv;
|
|
+ struct timezone tz, *target_tz;
|
|
+ if (arg2 != 0) {
|
|
+ if (!lock_user_struct(VERIFY_READ, target_tz, arg2, 0))
|
|
+ goto efault;
|
|
+ __get_user(tz.tz_minuteswest,
|
|
+ &target_tz->tz_minuteswest);
|
|
+ __get_user(tz.tz_dsttime, &target_tz->tz_dsttime);
|
|
+ unlock_user_struct(target_tz, arg2, 1);
|
|
+ }
|
|
+ ret = get_errno(gettimeofday(&tv, arg2 != 0 ? &tz : NULL));
|
|
+ if (!is_error(ret)) {
|
|
+ if (fbsd_copy_to_user_timeval(&tv, arg1))
|
|
+ goto efault;
|
|
+ }
|
|
+ }
|
|
+ break;
|
|
+
|
|
+ case TARGET_FREEBSD_NR_settimeofday:
|
|
+ {
|
|
+ struct timeval tv;
|
|
+ struct timezone tz, *target_tz;
|
|
+
|
|
+ if (arg2 != 0) {
|
|
+ if (!lock_user_struct(VERIFY_READ, target_tz, arg2, 0))
|
|
+ goto efault;
|
|
+ __get_user(tz.tz_minuteswest,
|
|
+ &target_tz->tz_minuteswest);
|
|
+ __get_user(tz.tz_dsttime, &target_tz->tz_dsttime);
|
|
+ unlock_user_struct(target_tz, arg2, 1);
|
|
+ }
|
|
+ if (copy_from_user_timeval(&tv, arg1))
|
|
+ goto efault;
|
|
+ ret = get_errno(settimeofday(&tv, arg2 != 0 ? & tz : NULL));
|
|
+ }
|
|
+ break;
|
|
+
|
|
+ case TARGET_FREEBSD_NR_ktimer_create:
|
|
+ case TARGET_FREEBSD_NR_ktimer_delete:
|
|
+ case TARGET_FREEBSD_NR_ktimer_settime:
|
|
+ case TARGET_FREEBSD_NR_ktimer_gettime:
|
|
+ case TARGET_FREEBSD_NR_ktimer_getoverrun:
|
|
+ case TARGET_FREEBSD_NR_minherit:
|
|
+ ret = unimplemented(num);
|
|
+ break;
|
|
+
|
|
+ case TARGET_FREEBSD_NR_kqueue:
|
|
+ ret = get_errno(kqueue());
|
|
+ break;
|
|
+
|
|
+#ifdef __FreeBSD__
|
|
+ case TARGET_FREEBSD_NR_kevent:
|
|
+ {
|
|
+ struct kevent *changelist = NULL, *eventlist = NULL;
|
|
+ struct target_kevent *target_changelist, *target_eventlist;
|
|
+ struct timespec ts;
|
|
+ int i;
|
|
+
|
|
+ if (arg3 != 0) {
|
|
+ if (!(target_changelist = lock_user(VERIFY_READ, arg2,
|
|
+ sizeof(struct target_kevent) * arg3, 1)))
|
|
+ goto efault;
|
|
+ changelist = alloca(sizeof(struct kevent) * arg3);
|
|
+
|
|
+ for (i = 0; i < arg3; i++) {
|
|
+ __get_user(changelist[i].ident, &target_changelist[i].ident);
|
|
+ __get_user(changelist[i].filter, &target_changelist[i].filter);
|
|
+ __get_user(changelist[i].flags, &target_changelist[i].flags);
|
|
+ __get_user(changelist[i].fflags, &target_changelist[i].fflags);
|
|
+ __get_user(changelist[i].data, &target_changelist[i].data);
|
|
+ /* XXX: This is broken when running a 64bits target on a 32bits host */
|
|
+ /* __get_user(changelist[i].udata, &target_changelist[i].udata); */
|
|
+#if TARGET_ABI_BITS == 32
|
|
+ changelist[i].udata = (void *)(uintptr_t)target_changelist[i].udata;
|
|
+ tswap32s((uint32_t *)&changelist[i].udata);
|
|
+#else
|
|
+ changelist[i].udata = (void *)(uintptr_t)target_changelist[i].udata;
|
|
+ tswap64s((uint64_t *)&changelist[i].udata);
|
|
+#endif
|
|
+ }
|
|
+ unlock_user(target_changelist, arg2, 0);
|
|
+ }
|
|
+
|
|
+ if (arg5 != 0)
|
|
+ eventlist = alloca(sizeof(struct kevent) * arg5);
|
|
+ if (arg6 != 0)
|
|
+ if (target_to_host_timespec(&ts, arg6))
|
|
+ goto efault;
|
|
+ ret = get_errno(kevent(arg1, changelist, arg3, eventlist, arg5,
|
|
+ arg6 != 0 ? &ts : NULL));
|
|
+ if (!is_error(ret)) {
|
|
+ if (!(target_eventlist = lock_user(VERIFY_WRITE, arg4,
|
|
+ sizeof(struct target_kevent) * arg5, 0)))
|
|
+ goto efault;
|
|
+ for (i = 0; i < arg5; i++) {
|
|
+ __put_user(eventlist[i].ident, &target_eventlist[i].ident);
|
|
+ __put_user(eventlist[i].filter, &target_eventlist[i].filter);
|
|
+ __put_user(eventlist[i].flags, &target_eventlist[i].flags);
|
|
+ __put_user(eventlist[i].fflags, &target_eventlist[i].fflags);
|
|
+ __put_user(eventlist[i].data, &target_eventlist[i].data);
|
|
+ /* __put_user(eventlist[i].udata, &target_eventlist[i].udata); */
|
|
+#if TARGET_ABI_BITS == 32
|
|
+ tswap32s((uint32_t *)&eventlist[i].data);
|
|
+ target_eventlist[i].data = (uintptr_t)eventlist[i].data;
|
|
+#else
|
|
+ tswap64s((uint64_t *)&eventlist[i].data);
|
|
+ target_eventlist[i].data = (uintptr_t)eventlist[i].data;
|
|
+#endif
|
|
+ }
|
|
+ unlock_user(target_eventlist, arg4, sizeof(struct target_kevent) * arg5);
|
|
+
|
|
+
|
|
+ }
|
|
+ }
|
|
+ break;
|
|
+#endif
|
|
+
|
|
+ case TARGET_FREEBSD_NR_execve:
|
|
+ {
|
|
+ char **argp, **envp;
|
|
+ int argc, envc;
|
|
+ abi_ulong gp;
|
|
+ abi_ulong guest_argp;
|
|
+ abi_ulong guest_envp;
|
|
+ abi_ulong addr;
|
|
+ char **q;
|
|
+ int total_size = 0;
|
|
+
|
|
+ argc = 0;
|
|
+ guest_argp = arg2;
|
|
+ for (gp = guest_argp; gp; gp += sizeof(abi_ulong)) {
|
|
+ if (get_user_ual(addr, gp))
|
|
+ goto efault;
|
|
+ if (!addr)
|
|
+ break;
|
|
+ argc++;
|
|
+ }
|
|
+ envc = 0;
|
|
+ guest_envp = arg3;
|
|
+ for (gp = guest_envp; gp; gp += sizeof(abi_ulong)) {
|
|
+ if (get_user_ual(addr, gp))
|
|
+ goto efault;
|
|
+ if (!addr)
|
|
+ break;
|
|
+ envc++;
|
|
+ }
|
|
+
|
|
+ argp = alloca((argc + 1) * sizeof(void *));
|
|
+ envp = alloca((envc + 1) * sizeof(void *));
|
|
+
|
|
+ for (gp = guest_argp, q = argp; gp;
|
|
+ gp += sizeof(abi_ulong), q++) {
|
|
+ if (get_user_ual(addr, gp))
|
|
+ goto execve_efault;
|
|
+ if (!addr)
|
|
+ break;
|
|
+ if (!(*q = lock_user_string(addr)))
|
|
+ goto execve_efault;
|
|
+ total_size += strlen(*q) + 1;
|
|
+ }
|
|
+ *q = NULL;
|
|
+
|
|
+ for (gp = guest_envp, q = envp; gp;
|
|
+ gp += sizeof(abi_ulong), q++) {
|
|
+ if (get_user_ual(addr, gp))
|
|
+ goto execve_efault;
|
|
+ if (!addr)
|
|
+ break;
|
|
+ if (!(*q = lock_user_string(addr)))
|
|
+ goto execve_efault;
|
|
+ total_size += strlen(*q) + 1;
|
|
+ }
|
|
+ *q = NULL;
|
|
+
|
|
+ /* This case will not be caught by the host's execve() if its
|
|
+ page size is bigger than the target's. */
|
|
+ if (total_size > MAX_ARG_PAGES * TARGET_PAGE_SIZE) {
|
|
+ ret = -TARGET_E2BIG;
|
|
+ goto execve_end;
|
|
+ }
|
|
+ if (!(p = lock_user_string(arg1)))
|
|
+ goto execve_efault;
|
|
+ ret = get_errno(execve(p, argp, envp));
|
|
+ unlock_user(p, arg1, 0);
|
|
+
|
|
+ goto execve_end;
|
|
+
|
|
+ execve_efault:
|
|
+ ret = -TARGET_EFAULT;
|
|
+
|
|
+ execve_end:
|
|
+ for (gp = guest_argp, q = argp; *q;
|
|
+ gp += sizeof(abi_ulong), q++) {
|
|
+ if (get_user_ual(addr, gp)
|
|
+ || !addr)
|
|
+ break;
|
|
+ unlock_user(*q, addr, 0);
|
|
+ }
|
|
+ for (gp = guest_envp, q = envp; *q;
|
|
+ gp += sizeof(abi_ulong), q++) {
|
|
+ if (get_user_ual(addr, gp)
|
|
+ || !addr)
|
|
+ break;
|
|
+ unlock_user(*q, addr, 0);
|
|
+ }
|
|
+ }
|
|
+ break;
|
|
+
|
|
+ case TARGET_FREEBSD_NR_pipe:
|
|
+ {
|
|
+ int host_pipe[2];
|
|
+ int host_ret = pipe(host_pipe);
|
|
+
|
|
+ if (!is_error(host_ret)) {
|
|
+ set_second_rval(cpu_env, host_pipe[1]);
|
|
+ ret = host_pipe[0];
|
|
+ } else
|
|
+ ret = get_errno(host_ret);
|
|
+ }
|
|
+ break;
|
|
+
|
|
+ case TARGET_FREEBSD_NR_lseek:
|
|
+ {
|
|
+#if defined(TARGET_MIPS) && TARGET_ABI_BITS == 32
|
|
+ /* 32-bit MIPS uses two 32 registers for 64 bit arguments */
|
|
+ int64_t res = lseek(arg1, target_offset64(arg2, arg3), arg4);
|
|
+
|
|
+ if (res == -1) {
|
|
+ ret = get_errno(res);
|
|
+ } else {
|
|
+ ret = res & 0xFFFFFFFF;
|
|
+ ((CPUMIPSState*)cpu_env)->active_tc.gpr[3] =
|
|
+ (res >> 32) & 0xFFFFFFFF;
|
|
+ }
|
|
+#else
|
|
+ ret = get_errno(lseek(arg1, arg2, arg3));
|
|
+#endif
|
|
+ }
|
|
+ break;
|
|
+
|
|
+ case TARGET_FREEBSD_NR_select:
|
|
+ ret = do_freebsd_select(arg1, arg2, arg3, arg4, arg5);
|
|
+ break;
|
|
+
|
|
+ case TARGET_FREEBSD_NR_pselect:
|
|
+ ret = do_freebsd_pselect(arg1, arg2, arg3, arg4, arg5, arg6);
|
|
+ break;
|
|
+
|
|
+ case TARGET_FREEBSD_NR_poll:
|
|
+ {
|
|
+ nfds_t i, nfds = arg2;
|
|
+ int timeout = arg3;
|
|
+ struct pollfd *pfd;
|
|
+ struct target_pollfd *target_pfd = lock_user(VERIFY_WRITE, arg1,
|
|
+ sizeof(struct target_pollfd) * nfds, 1);
|
|
+
|
|
+ if (!target_pfd)
|
|
+ goto efault;
|
|
+
|
|
+ pfd = alloca(sizeof(struct pollfd) * nfds);
|
|
+ for(i = 0; i < nfds; i++) {
|
|
+ pfd[i].fd = tswap32(target_pfd[i].fd);
|
|
+ pfd[i].events = tswap16(target_pfd[i].events);
|
|
+ }
|
|
+ ret = get_errno(poll(pfd, nfds, timeout));
|
|
+
|
|
+ if (!is_error(ret)) {
|
|
+ for(i = 0; i < nfds; i++) {
|
|
+ target_pfd[i].revents = tswap16(pfd[i].revents);
|
|
+ }
|
|
+ }
|
|
+ unlock_user(target_pfd, arg1, sizeof(struct target_pollfd) *
|
|
+ nfds);
|
|
+ }
|
|
+ break;
|
|
+
|
|
+ case TARGET_FREEBSD_NR_openbsd_poll:
|
|
+ ret = unimplemented(num);
|
|
+ break;
|
|
+
|
|
+ case TARGET_FREEBSD_NR_setrlimit:
|
|
+ {
|
|
+ int resource = target_to_host_resource(arg1);
|
|
+ struct target_rlimit *target_rlim;
|
|
+ struct rlimit rlim;
|
|
+
|
|
+ if (!lock_user_struct(VERIFY_READ, target_rlim, arg2, 1))
|
|
+ goto efault;
|
|
+ rlim.rlim_cur = target_to_host_rlim(target_rlim->rlim_cur);
|
|
+ rlim.rlim_max = target_to_host_rlim(target_rlim->rlim_max);
|
|
+ unlock_user_struct(target_rlim, arg2, 0);
|
|
+ ret = get_errno(setrlimit(resource, &rlim));
|
|
+ }
|
|
+ break;
|
|
+
|
|
+
|
|
+ case TARGET_FREEBSD_NR_getrlimit:
|
|
+ {
|
|
+ int resource = target_to_host_resource(arg1);
|
|
+ struct target_rlimit *target_rlim;
|
|
+ struct rlimit rlim;
|
|
+
|
|
+ ret = get_errno(getrlimit(resource, &rlim));
|
|
+ if (!is_error(ret)) {
|
|
+ if (!lock_user_struct(VERIFY_WRITE, target_rlim, arg2,
|
|
+ 0))
|
|
+ goto efault;
|
|
+ target_rlim->rlim_cur =
|
|
+ host_to_target_rlim(rlim.rlim_cur);
|
|
+ target_rlim->rlim_max =
|
|
+ host_to_target_rlim(rlim.rlim_max);
|
|
+ unlock_user_struct(target_rlim, arg2, 1);
|
|
+ }
|
|
+ }
|
|
+ break;
|
|
+
|
|
+ case TARGET_FREEBSD_NR_setitimer:
|
|
+ {
|
|
+ struct itimerval value, ovalue, *pvalue;
|
|
+
|
|
+ if (arg2) {
|
|
+ pvalue = &value;
|
|
+ if (copy_from_user_timeval(&pvalue->it_interval,
|
|
+ arg2) || copy_from_user_timeval(
|
|
+ &pvalue->it_value, arg2 +
|
|
+ sizeof(struct target_timeval)))
|
|
+ goto efault;
|
|
+ } else {
|
|
+ pvalue = NULL;
|
|
+ }
|
|
+ ret = get_errno(setitimer(arg1, pvalue, &ovalue));
|
|
+ if (!is_error(ret) && arg3) {
|
|
+ if (fbsd_copy_to_user_timeval(&ovalue.it_interval, arg3)
|
|
+ || fbsd_copy_to_user_timeval(&ovalue.it_value,
|
|
+ arg3 + sizeof(struct target_timeval)))
|
|
+ goto efault;
|
|
+ }
|
|
+ }
|
|
+ break;
|
|
+
|
|
+ case TARGET_FREEBSD_NR_getitimer:
|
|
+ {
|
|
+ struct itimerval value;
|
|
+
|
|
+ ret = get_errno(getitimer(arg1, &value));
|
|
+ if (!is_error(ret) && arg2) {
|
|
+ if (fbsd_copy_to_user_timeval(&value.it_interval, arg2)
|
|
+ || fbsd_copy_to_user_timeval(&value.it_value,
|
|
+ arg2 + sizeof(struct target_timeval)))
|
|
+ goto efault;
|
|
+ }
|
|
+ }
|
|
+ break;
|
|
+
|
|
+ case TARGET_FREEBSD_NR_utimes:
|
|
+ {
|
|
+ struct timeval *tvp, tv[2];
|
|
+
|
|
+ if (arg2) {
|
|
+ if (copy_from_user_timeval(&tv[0], arg2)
|
|
+ || copy_from_user_timeval(&tv[1],
|
|
+ arg2 + sizeof(struct target_timeval)))
|
|
+
|
|
+ goto efault;
|
|
+ tvp = tv;
|
|
+ } else {
|
|
+ tvp = NULL;
|
|
+ }
|
|
+ if (!(p = lock_user_string(arg1)))
|
|
+ goto efault;
|
|
+ ret = get_errno(utimes(p, tvp));
|
|
+ unlock_user(p, arg1, 0);
|
|
+ }
|
|
+ break;
|
|
+
|
|
+ case TARGET_FREEBSD_NR_lutimes:
|
|
+ {
|
|
+ struct timeval *tvp, tv[2];
|
|
+
|
|
+ if (arg2) {
|
|
+ if (copy_from_user_timeval(&tv[0], arg2)
|
|
+ || copy_from_user_timeval(&tv[1],
|
|
+ arg2 + sizeof(struct target_timeval)))
|
|
+
|
|
+ goto efault;
|
|
+ tvp = tv;
|
|
+ } else {
|
|
+ tvp = NULL;
|
|
+ }
|
|
+ if (!(p = lock_user_string(arg1)))
|
|
+ goto efault;
|
|
+ ret = get_errno(lutimes(p, tvp));
|
|
+ unlock_user(p, arg1, 0);
|
|
+ }
|
|
+ break;
|
|
+
|
|
+ case TARGET_FREEBSD_NR_futimes:
|
|
+ {
|
|
+ struct timeval *tvp, tv[2];
|
|
+
|
|
+ if (arg2) {
|
|
+ if (copy_from_user_timeval(&tv[0], arg2)
|
|
+ || copy_from_user_timeval(&tv[1],
|
|
+ arg2 + sizeof(struct target_timeval)))
|
|
+ goto efault;
|
|
+ tvp = tv;
|
|
+ } else {
|
|
+ tvp = NULL;
|
|
+ }
|
|
+ ret = get_errno(futimes(arg1, tvp));
|
|
+ }
|
|
+ break;
|
|
+
|
|
+ case TARGET_FREEBSD_NR_futimesat:
|
|
+ {
|
|
+ struct timeval *tvp, tv[2];
|
|
+
|
|
+ if (arg3) {
|
|
+ if (copy_from_user_timeval(&tv[0], arg3)
|
|
+ || copy_from_user_timeval(&tv[1],
|
|
+ arg3 + sizeof(struct target_timeval)))
|
|
+ goto efault;
|
|
+ tvp = tv;
|
|
+ } else {
|
|
+ tvp = NULL;
|
|
+ }
|
|
+ if (!(p = lock_user_string(arg2)))
|
|
+ goto efault;
|
|
+ ret = get_errno(futimesat(arg1, path(p), tvp));
|
|
+ unlock_user(p, arg2, 0);
|
|
+ }
|
|
+ break;
|
|
+
|
|
+ case TARGET_FREEBSD_NR_access:
|
|
+ if (!(p = lock_user_string(arg1)))
|
|
+ goto efault;
|
|
+ ret = get_errno(access(path(p), arg2));
|
|
+ unlock_user(p, arg1, 0);
|
|
+
|
|
+ case TARGET_FREEBSD_NR_eaccess:
|
|
+ if (!(p = lock_user_string(arg1)))
|
|
+ goto efault;
|
|
+ ret = get_errno(eaccess(path(p), arg2));
|
|
+ unlock_user(p, arg1, 0);
|
|
+ break;
|
|
+
|
|
+ case TARGET_FREEBSD_NR_faccessat:
|
|
+ if (!(p = lock_user_string(arg2)))
|
|
+ goto efault;
|
|
+ ret = get_errno(faccessat(arg1, p, arg3, arg4));
|
|
+ unlock_user(p, arg2, 0);
|
|
+ break;
|
|
+
|
|
+ case TARGET_FREEBSD_NR_chdir:
|
|
+ if (!(p = lock_user_string(arg1)))
|
|
+ goto efault;
|
|
+ ret = get_errno(chdir(p));
|
|
+ unlock_user(p, arg1, 0);
|
|
+ break;
|
|
+
|
|
+ case TARGET_FREEBSD_NR_fchdir:
|
|
+ ret = get_errno(fchdir(arg1));
|
|
+ break;
|
|
+
|
|
+ case TARGET_FREEBSD_NR_rename:
|
|
+ {
|
|
+ void *p2;
|
|
+
|
|
+ p = lock_user_string(arg1);
|
|
+ p2 = lock_user_string(arg2);
|
|
+ if (!p || !p2)
|
|
+ ret = -TARGET_EFAULT;
|
|
+ else
|
|
+ ret = get_errno(rename(p, p2));
|
|
+ unlock_user(p2, arg2, 0);
|
|
+ unlock_user(p, arg1, 0);
|
|
+ }
|
|
+ break;
|
|
+
|
|
+ case TARGET_FREEBSD_NR_renameat:
|
|
+ {
|
|
+ void *p2;
|
|
+
|
|
+ p = lock_user_string(arg2);
|
|
+ p2 = lock_user_string(arg4);
|
|
+ if (!p || !p2)
|
|
+ ret = -TARGET_EFAULT;
|
|
+ else
|
|
+ ret = get_errno(renameat(arg1, p, arg3, p2));
|
|
+ unlock_user(p2, arg4, 0);
|
|
+ unlock_user(p, arg2, 0);
|
|
+ }
|
|
+ break;
|
|
+
|
|
+ case TARGET_FREEBSD_NR_link:
|
|
+ {
|
|
+ void * p2;
|
|
+
|
|
+ p = lock_user_string(arg1);
|
|
+ p2 = lock_user_string(arg2);
|
|
+ if (!p || !p2)
|
|
+ ret = -TARGET_EFAULT;
|
|
+ else
|
|
+ ret = get_errno(link(p, p2));
|
|
+ unlock_user(p2, arg2, 0);
|
|
+ unlock_user(p, arg1, 0);
|
|
+ }
|
|
+ break;
|
|
+
|
|
+ case TARGET_FREEBSD_NR_linkat:
|
|
+ {
|
|
+ void * p2 = NULL;
|
|
+
|
|
+ if (!arg2 || !arg4)
|
|
+ goto efault;
|
|
+
|
|
+ p = lock_user_string(arg2);
|
|
+ p2 = lock_user_string(arg4);
|
|
+ if (!p || !p2)
|
|
+ ret = -TARGET_EFAULT;
|
|
+ else
|
|
+ ret = get_errno(linkat(arg1, p, arg3, p2, arg5));
|
|
+ unlock_user(p, arg2, 0);
|
|
+ unlock_user(p2, arg4, 0);
|
|
+ }
|
|
+ break;
|
|
+
|
|
+ case TARGET_FREEBSD_NR_unlink:
|
|
+ if (!(p = lock_user_string(arg1)))
|
|
+ goto efault;
|
|
+ ret = get_errno(unlink(p));
|
|
+ unlock_user(p, arg1, 0);
|
|
+ break;
|
|
+
|
|
+ case TARGET_FREEBSD_NR_unlinkat:
|
|
+ if (!(p = lock_user_string(arg2)))
|
|
+ goto efault;
|
|
+ ret = get_errno(unlinkat(arg1, p, arg3));
|
|
+ unlock_user(p, arg2, 0);
|
|
+ break;
|
|
+
|
|
+ case TARGET_FREEBSD_NR_mkdir:
|
|
+ if (!(p = lock_user_string(arg1)))
|
|
+ goto efault;
|
|
+ ret = get_errno(mkdir(p, arg2));
|
|
+ unlock_user(p, arg1, 0);
|
|
+ break;
|
|
+
|
|
+ case TARGET_FREEBSD_NR_mkdirat:
|
|
+ if (!(p = lock_user_string(arg2)))
|
|
+ goto efault;
|
|
+ ret = get_errno(mkdirat(arg1, p, arg3));
|
|
+ unlock_user(p, arg2, 0);
|
|
+ break;
|
|
+
|
|
+ case TARGET_FREEBSD_NR_rmdir:
|
|
+ if (!(p = lock_user_string(arg1)))
|
|
+ goto efault;
|
|
+ ret = get_errno(rmdir(p));
|
|
+ unlock_user(p, arg1, 0);
|
|
+ break;
|
|
+
|
|
+ case TARGET_FREEBSD_NR___getcwd:
|
|
+ if (!(p = lock_user(VERIFY_WRITE, arg1, arg2, 0)))
|
|
+ goto efault;
|
|
+ ret = get_errno(__getcwd(p, arg2));
|
|
+ unlock_user(p, arg1, ret);
|
|
+ break;
|
|
+
|
|
+ case TARGET_FREEBSD_NR_dup:
|
|
+ ret = get_errno(dup(arg1));
|
|
+ break;
|
|
+
|
|
+ case TARGET_FREEBSD_NR_dup2:
|
|
+ ret = get_errno(dup2(arg1, arg2));
|
|
+ break;
|
|
+
|
|
+ case TARGET_FREEBSD_NR_truncate:
|
|
+ if (!(p = lock_user_string(arg1)))
|
|
+ goto efault;
|
|
+ if (regpairs_aligned(cpu_env)) {
|
|
+ arg2 = arg3;
|
|
+ arg3 = arg4;
|
|
+ }
|
|
+ ret = get_errno(truncate(p, target_offset64(arg2, arg3)));
|
|
+ unlock_user(p, arg1, 0);
|
|
+ break;
|
|
+
|
|
+ case TARGET_FREEBSD_NR_ftruncate:
|
|
+ if (regpairs_aligned(cpu_env)) {
|
|
+ arg2 = arg3;
|
|
+ arg3 = arg4;
|
|
+ }
|
|
+ ret = get_errno(ftruncate(arg1, target_offset64(arg2, arg3)));
|
|
+ break;
|
|
+
|
|
+ case TARGET_FREEBSD_NR_acct:
|
|
+ if (arg1 == 0) {
|
|
+ ret = get_errno(acct(NULL));
|
|
+ } else {
|
|
+ if (!(p = lock_user_string(arg1)))
|
|
+ goto efault;
|
|
+ ret = get_errno(acct(path(p)));
|
|
+ unlock_user(p, arg1, 0);
|
|
+ }
|
|
+ break;
|
|
+
|
|
+ case TARGET_FREEBSD_NR_sync:
|
|
+ sync();
|
|
+ ret = 0;
|
|
+ break;
|
|
+
|
|
+ case TARGET_FREEBSD_NR_mount:
|
|
+ {
|
|
+ void *p2;
|
|
+
|
|
+ /* We need to look at the data field. */
|
|
+ p = lock_user_string(arg1); /* type */
|
|
+ p2 = lock_user_string(arg2); /* dir */
|
|
+ if (!p || !p2)
|
|
+ ret = -TARGET_EFAULT;
|
|
+ else {
|
|
+ /*
|
|
+ * XXX arg5 should be locked, but it isn't clear
|
|
+ * how to do that since it's it may be not be a
|
|
+ * NULL-terminated string.
|
|
+ */
|
|
+ if ( ! arg5 )
|
|
+ ret = get_errno(mount(p, p2, arg3, NULL));
|
|
+ else
|
|
+ ret = get_errno(mount(p, p2, arg3, g2h(arg5)));
|
|
+ }
|
|
+ unlock_user(p, arg1, 0);
|
|
+ unlock_user(p2, arg1, 0);
|
|
+ }
|
|
+ break;
|
|
+
|
|
+ case TARGET_FREEBSD_NR_unmount:
|
|
+ if (!(p = lock_user_string(arg1)))
|
|
+ goto efault;
|
|
+ ret = get_errno(unmount(p, arg2));
|
|
+ unlock_user(p, arg1, 0);
|
|
+ break;
|
|
+
|
|
+ case TARGET_FREEBSD_NR_nmount:
|
|
+ {
|
|
+ int count = arg2;
|
|
+ struct iovec *vec;
|
|
+
|
|
+ vec = alloca(count * sizeof(struct iovec));
|
|
+ if (lock_iovec(VERIFY_READ, vec, arg2, count, 1) < 0)
|
|
+ goto efault;
|
|
+ ret = get_errno(nmount(vec, count, arg3));
|
|
+ unlock_iovec(vec, arg2, count, 0);
|
|
+ }
|
|
+ break;
|
|
+
|
|
+ case TARGET_FREEBSD_NR_symlink:
|
|
+ {
|
|
+ void *p2;
|
|
+
|
|
+ p = lock_user_string(arg1);
|
|
+ p2 = lock_user_string(arg2);
|
|
+ if (!p || !p2)
|
|
+ ret = -TARGET_EFAULT;
|
|
+ else
|
|
+ ret = get_errno(symlink(p, p2));
|
|
+ unlock_user(p2, arg2, 0);
|
|
+ unlock_user(p, arg1, 0);
|
|
+ }
|
|
+ break;
|
|
+
|
|
+ case TARGET_FREEBSD_NR_symlinkat:
|
|
+ {
|
|
+ void *p2;
|
|
+
|
|
+ p = lock_user_string(arg1);
|
|
+ p2 = lock_user_string(arg3);
|
|
+ if (!p || !p2)
|
|
+ ret = -TARGET_EFAULT;
|
|
+ else
|
|
+ ret = get_errno(symlinkat(p, arg2, p2));
|
|
+ unlock_user(p2, arg3, 0);
|
|
+ unlock_user(p, arg1, 0);
|
|
+ }
|
|
+ break;
|
|
+
|
|
+ case TARGET_FREEBSD_NR_readlink:
|
|
+ {
|
|
+ void *p2;
|
|
+
|
|
+ p = lock_user_string(arg1);
|
|
+ p2 = lock_user(VERIFY_WRITE, arg2, arg3, 0);
|
|
+ if (!p || !p2)
|
|
+ ret = -TARGET_EFAULT;
|
|
+ else
|
|
+ ret = get_errno(readlink(path(p), p2, arg3));
|
|
+ unlock_user(p2, arg2, ret);
|
|
+ unlock_user(p, arg1, 0);
|
|
+ }
|
|
+ break;
|
|
+
|
|
+ case TARGET_FREEBSD_NR_readlinkat:
|
|
+ {
|
|
+ void *p2;
|
|
+ p = lock_user_string(arg2);
|
|
+ p2 = lock_user(VERIFY_WRITE, arg3, arg4, 0);
|
|
+
|
|
+ if (!p || !p2)
|
|
+ ret = -TARGET_EFAULT;
|
|
+ else
|
|
+ ret = get_errno(readlinkat(arg1, path(p), p2, arg4));
|
|
+ unlock_user(p2, arg3, ret);
|
|
+ unlock_user(p, arg2, 0);
|
|
+ }
|
|
+ break;
|
|
+
|
|
+ case TARGET_FREEBSD_NR_chmod:
|
|
+ if (!(p = lock_user_string(arg1)))
|
|
+ goto efault;
|
|
+ ret = get_errno(chmod(p, arg2));
|
|
+ unlock_user(p, arg1, 0);
|
|
+ break;
|
|
+
|
|
+ case TARGET_FREEBSD_NR_fchmod:
|
|
+ ret = get_errno(fchmod(arg1, arg2));
|
|
+ break;
|
|
+
|
|
+ case TARGET_FREEBSD_NR_lchmod:
|
|
+ if (!(p = lock_user_string(arg1)))
|
|
+ goto efault;
|
|
+ ret = get_errno(lchmod(p, arg2));
|
|
+ unlock_user(p, arg1, 0);
|
|
+ break;
|
|
+
|
|
+ case TARGET_FREEBSD_NR_fchmodat:
|
|
+ if (!(p = lock_user_string(arg2)))
|
|
+ goto efault;
|
|
+ ret = get_errno(fchmodat(arg1, p, arg3, arg4));
|
|
+ unlock_user(p, arg2, 0);
|
|
+ break;
|
|
+
|
|
+ case TARGET_FREEBSD_NR_mknod:
|
|
+ if (!(p = lock_user_string(arg1)))
|
|
+ goto efault;
|
|
+ ret = get_errno(mknod(p, arg2, arg3));
|
|
+ unlock_user(p, arg1, 0);
|
|
+ break;
|
|
+
|
|
+ case TARGET_FREEBSD_NR_mknodat:
|
|
+ if (!(p = lock_user_string(arg2)))
|
|
+ goto efault;
|
|
+ ret = get_errno(mknodat(arg1, p, arg3, arg4));
|
|
+ unlock_user(p, arg2, 0);
|
|
+ break;
|
|
+
|
|
+ case TARGET_FREEBSD_NR_chown:
|
|
+ if (!(p = lock_user_string(arg1)))
|
|
+ goto efault;
|
|
+ ret = get_errno(chown(p, arg2, arg3));
|
|
+ unlock_user(p, arg1, 0);
|
|
+ break;
|
|
+
|
|
+ case TARGET_FREEBSD_NR_fchown:
|
|
+ ret = get_errno(fchown(arg1, arg2, arg3));
|
|
+ break;
|
|
+
|
|
+ case TARGET_FREEBSD_NR_lchown:
|
|
+ if (!(p = lock_user_string(arg1)))
|
|
+ goto efault;
|
|
+ ret = get_errno(lchown(p, arg2, arg3));
|
|
+ unlock_user(p, arg1, 0);
|
|
+ break;
|
|
+
|
|
+ case TARGET_FREEBSD_NR_fchownat:
|
|
+ if (!(p = lock_user_string(arg2)))
|
|
+ goto efault;
|
|
+ ret = get_errno(fchownat(arg1, p, arg3, arg4, arg5));
|
|
+ unlock_user(p, arg2, 0);
|
|
+ break;
|
|
+
|
|
+ case TARGET_FREEBSD_NR_chflags:
|
|
+ if (!(p = lock_user_string(arg1)))
|
|
+ goto efault;
|
|
+ ret = get_errno(chflags(p, arg2));
|
|
+ unlock_user(p, arg1, 0);
|
|
+ break;
|
|
+
|
|
+ case TARGET_FREEBSD_NR_lchflags:
|
|
+ if (!(p = lock_user_string(arg1)))
|
|
+ goto efault;
|
|
+ ret = get_errno(lchflags(p, arg2));
|
|
+ unlock_user(p, arg1, 0);
|
|
+ break;
|
|
+
|
|
+ case TARGET_FREEBSD_NR_fchflags:
|
|
+ ret = get_errno(fchflags(arg1, arg2));
|
|
+ break;
|
|
+
|
|
+ case TARGET_FREEBSD_NR_getgroups:
|
|
+ {
|
|
+ int gidsetsize = arg1;
|
|
+ uint32_t *target_grouplist;
|
|
+ gid_t *grouplist;
|
|
+ int i;
|
|
+
|
|
+ grouplist = alloca(gidsetsize * sizeof(gid_t));
|
|
+ ret = get_errno(getgroups(gidsetsize, grouplist));
|
|
+ if (gidsetsize == 0)
|
|
+ break;
|
|
+ if (!is_error(ret)) {
|
|
+ target_grouplist = lock_user(VERIFY_WRITE, arg2,
|
|
+ gidsetsize * 2, 0);
|
|
+ if (!target_grouplist)
|
|
+ goto efault;
|
|
+ for (i = 0;i < ret; i++)
|
|
+ target_grouplist[i] = tswap32(grouplist[i]);
|
|
+ unlock_user(target_grouplist, arg2, gidsetsize * 2);
|
|
+ }
|
|
+ }
|
|
+ break;
|
|
+
|
|
+ case TARGET_FREEBSD_NR_setgroups:
|
|
+ {
|
|
+ int gidsetsize = arg1;
|
|
+ uint32_t *target_grouplist;
|
|
+ gid_t *grouplist;
|
|
+ int i;
|
|
+
|
|
+ grouplist = alloca(gidsetsize * sizeof(gid_t));
|
|
+ target_grouplist = lock_user(VERIFY_READ, arg2,
|
|
+ gidsetsize * 2, 1);
|
|
+ if (!target_grouplist) {
|
|
+ ret = -TARGET_EFAULT;
|
|
+ goto fail;
|
|
+ }
|
|
+ for(i = 0;i < gidsetsize; i++)
|
|
+ grouplist[i] = tswap32(target_grouplist[i]);
|
|
+ unlock_user(target_grouplist, arg2, 0);
|
|
+ ret = get_errno(setgroups(gidsetsize, grouplist));
|
|
+ }
|
|
+ break;
|
|
+
|
|
+ case TARGET_FREEBSD_NR_umask:
|
|
+ ret = get_errno(umask(arg1));
|
|
+ break;
|
|
+
|
|
+ case TARGET_FREEBSD_NR_fcntl:
|
|
+ {
|
|
+ int host_cmd;
|
|
+ struct flock fl;
|
|
+ struct target_flock *target_fl;
|
|
+
|
|
+ host_cmd = target_to_host_fcntl_cmd(arg2);
|
|
+ if (-TARGET_EINVAL == host_cmd) {
|
|
+ ret = host_cmd;
|
|
+ break;
|
|
+ }
|
|
+
|
|
+ switch(arg2) {
|
|
+ case TARGET_F_GETLK:
|
|
+ if (!lock_user_struct(VERIFY_READ, target_fl, arg3, 1))
|
|
+ return (-TARGET_EFAULT);
|
|
+ fl.l_type = tswap16(target_fl->l_type);
|
|
+ fl.l_whence = tswap16(target_fl->l_whence);
|
|
+ fl.l_start = tswapal(target_fl->l_start);
|
|
+ fl.l_len = tswapal(target_fl->l_len);
|
|
+ fl.l_pid = tswap32(target_fl->l_pid);
|
|
+ fl.l_sysid = tswap32(target_fl->l_sysid);
|
|
+ unlock_user_struct(target_fl, arg3, 0);
|
|
+ ret = get_errno(fcntl(arg1, host_cmd, &fl));
|
|
+ if (0 == ret) {
|
|
+ if (!lock_user_struct(VERIFY_WRITE, target_fl,
|
|
+ arg3, 0))
|
|
+ return (-TARGET_EFAULT);
|
|
+ target_fl->l_type = tswap16(fl.l_type);
|
|
+ target_fl->l_whence = tswap16(fl.l_whence);
|
|
+ target_fl->l_start = tswapal(fl.l_start);
|
|
+ target_fl->l_len = tswapal(fl.l_len);
|
|
+ target_fl->l_pid = tswap32(fl.l_pid);
|
|
+ target_fl->l_sysid = tswap32(fl.l_sysid);
|
|
+ unlock_user_struct(target_fl, arg3, 1);
|
|
+ }
|
|
+ break;
|
|
+
|
|
+ case TARGET_F_SETLK:
|
|
+ case TARGET_F_SETLKW:
|
|
+ if (!lock_user_struct(VERIFY_READ, target_fl, arg3, 1))
|
|
+ return (-TARGET_EFAULT);
|
|
+ fl.l_type = tswap16(target_fl->l_type);
|
|
+ fl.l_whence = tswap16(target_fl->l_whence);
|
|
+ fl.l_start = tswapal(target_fl->l_start);
|
|
+ fl.l_len = tswapal(target_fl->l_len);
|
|
+ fl.l_pid = tswap32(target_fl->l_pid);
|
|
+ fl.l_sysid = tswap32(target_fl->l_sysid);
|
|
+ unlock_user_struct(target_fl, arg3, 0);
|
|
+ ret = get_errno(fcntl(arg1, host_cmd, &fl));
|
|
+ break;
|
|
+
|
|
+ case TARGET_F_DUPFD:
|
|
+ case TARGET_F_DUP2FD:
|
|
+ case TARGET_F_GETOWN:
|
|
+ case TARGET_F_SETOWN:
|
|
+ case TARGET_F_GETFD:
|
|
+ case TARGET_F_SETFD:
|
|
+ case TARGET_F_GETFL:
|
|
+ case TARGET_F_SETFL:
|
|
+ case TARGET_F_READAHEAD:
|
|
+ case TARGET_F_RDAHEAD:
|
|
+ default:
|
|
+ ret = get_errno(fcntl(arg1, host_cmd, arg3));
|
|
+ break;
|
|
+ }
|
|
+ }
|
|
+ break;
|
|
+
|
|
+ case TARGET_FREEBSD_NR_getdents:
|
|
+ {
|
|
+ struct dirent *dirp;
|
|
+ int32_t nbytes = arg3;
|
|
+
|
|
+ if (!(dirp = lock_user(VERIFY_WRITE, arg2, nbytes, 0)))
|
|
+ goto efault;
|
|
+ ret = get_errno(getdents(arg1, (char *)dirp, nbytes));
|
|
+ if (!is_error(ret)) {
|
|
+ struct dirent *de;
|
|
+ int len = ret;
|
|
+ int reclen;
|
|
+
|
|
+ de = dirp;
|
|
+ while (len > 0) {
|
|
+ reclen = de->d_reclen;
|
|
+ if (reclen > len)
|
|
+ break;
|
|
+ de->d_reclen = tswap16(reclen);
|
|
+ len -= reclen;
|
|
+ }
|
|
+ }
|
|
+ unlock_user(dirp, arg2, ret);
|
|
+ }
|
|
+ break;
|
|
+
|
|
+ case TARGET_FREEBSD_NR_getdirentries:
|
|
+ {
|
|
+ struct dirent *dirp;
|
|
+ int32_t nbytes = arg3;
|
|
+ long basep;
|
|
+
|
|
+ if (!(dirp = lock_user(VERIFY_WRITE, arg2, nbytes, 0)))
|
|
+ goto efault;
|
|
+ ret = get_errno(getdirentries(arg1, (char *)dirp, nbytes,
|
|
+ &basep));
|
|
+ if (!is_error(ret)) {
|
|
+ struct dirent *de;
|
|
+ int len = ret;
|
|
+ int reclen;
|
|
+
|
|
+ de = dirp;
|
|
+ while (len > 0) {
|
|
+ reclen = de->d_reclen;
|
|
+ if (reclen > len)
|
|
+ break;
|
|
+ de->d_reclen = tswap16(reclen);
|
|
+ len -= reclen;
|
|
+ }
|
|
+ }
|
|
+ unlock_user(dirp, arg2, ret);
|
|
+ if (arg4)
|
|
+ if (put_user(nbytes, arg4, abi_ulong))
|
|
+ ret = -TARGET_EFAULT;
|
|
+ }
|
|
+ break;
|
|
+
|
|
+ case TARGET_FREEBSD_NR_chroot:
|
|
+ if (!(p = lock_user_string(arg1)))
|
|
+ goto efault;
|
|
+ ret = get_errno(chroot(p));
|
|
+ unlock_user(p, arg1, 0);
|
|
+ break;
|
|
+
|
|
+ case TARGET_FREEBSD_NR_flock:
|
|
+ ret = get_errno(flock(arg1, arg2));
|
|
+ break;
|
|
+
|
|
+ case TARGET_FREEBSD_NR_mkfifo:
|
|
+ if (!(p = lock_user_string(arg1)))
|
|
+ goto efault;
|
|
+ ret = get_errno(mkfifo(p, arg2));
|
|
+ unlock_user(p, arg1, 0);
|
|
+ break;
|
|
+
|
|
+ case TARGET_FREEBSD_NR_mkfifoat:
|
|
+ if (!(p = lock_user_string(arg2)))
|
|
+ goto efault;
|
|
+ ret = get_errno(mkfifoat(arg1, p, arg2));
|
|
+ unlock_user(p, arg2, 0);
|
|
+ break;
|
|
+
|
|
+ case TARGET_FREEBSD_NR_pathconf:
|
|
+ if (!(p = lock_user_string(arg1)))
|
|
+ goto efault;
|
|
+ ret = get_errno(pathconf(p, arg2));
|
|
+ unlock_user(p, arg1, 0);
|
|
+ break;
|
|
+
|
|
+ case TARGET_FREEBSD_NR_lpathconf:
|
|
+ if (!(p = lock_user_string(arg1)))
|
|
+ goto efault;
|
|
+ ret = get_errno(lpathconf(p, arg2));
|
|
+ unlock_user(p, arg1, 0);
|
|
+ break;
|
|
+
|
|
+ case TARGET_FREEBSD_NR_fpathconf:
|
|
+ ret = get_errno(fpathconf(arg1, arg2));
|
|
+ break;
|
|
+
|
|
+ case TARGET_FREEBSD_NR_undelete:
|
|
+ if (!(p = lock_user_string(arg1)))
|
|
+ goto efault;
|
|
+ ret = get_errno(undelete(p));
|
|
+ unlock_user(p, arg1, 0);
|
|
+ break;
|
|
+
|
|
+
|
|
+ case TARGET_FREEBSD_NR___acl_get_file:
|
|
+ case TARGET_FREEBSD_NR___acl_set_file:
|
|
+ case TARGET_FREEBSD_NR___acl_get_fd:
|
|
+ case TARGET_FREEBSD_NR___acl_set_fd:
|
|
+ case TARGET_FREEBSD_NR___acl_delete_file:
|
|
+ case TARGET_FREEBSD_NR___acl_delete_fd:
|
|
+ case TARGET_FREEBSD_NR___acl_aclcheck_file:
|
|
+ case TARGET_FREEBSD_NR___acl_aclcheck_fd:
|
|
+ case TARGET_FREEBSD_NR___acl_get_link:
|
|
+ case TARGET_FREEBSD_NR___acl_set_link:
|
|
+ case TARGET_FREEBSD_NR___acl_delete_link:
|
|
+ case TARGET_FREEBSD_NR___acl_aclcheck_link:
|
|
+ case TARGET_FREEBSD_NR_extattrctl:
|
|
+ case TARGET_FREEBSD_NR_extattr_set_file:
|
|
+ case TARGET_FREEBSD_NR_extattr_get_file:
|
|
+ case TARGET_FREEBSD_NR_extattr_delete_file:
|
|
+ case TARGET_FREEBSD_NR_extattr_set_fd:
|
|
+ case TARGET_FREEBSD_NR_extattr_get_fd:
|
|
+ case TARGET_FREEBSD_NR_extattr_delete_fd:
|
|
+ case TARGET_FREEBSD_NR_extattr_get_link:
|
|
+ case TARGET_FREEBSD_NR_extattr_set_link:
|
|
+ case TARGET_FREEBSD_NR_extattr_delete_link:
|
|
+ case TARGET_FREEBSD_NR_extattr_list_fd:
|
|
+ case TARGET_FREEBSD_NR_extattr_list_file:
|
|
+ case TARGET_FREEBSD_NR_extattr_list_link:
|
|
+ ret = unimplemented(num);
|
|
+ break;
|
|
+
|
|
+ case TARGET_FREEBSD_NR_setlogin:
|
|
+ if (!(p = lock_user_string(arg1)))
|
|
+ goto efault;
|
|
+ ret = get_errno(setlogin(p));
|
|
+ unlock_user(p, arg1, 0);
|
|
+ break;
|
|
+
|
|
+ case TARGET_FREEBSD_NR_getlogin:
|
|
+ if (!(p = lock_user_string(arg1)))
|
|
+ goto efault;
|
|
+ ret = get_errno(_getlogin(p, arg2));
|
|
+ unlock_user(p, arg1, 0);
|
|
+ break;
|
|
+
|
|
+ case TARGET_FREEBSD_NR_setloginclass:
|
|
+ if (!(p = lock_user_string(arg1)))
|
|
+ goto efault;
|
|
+ ret = get_errno(setloginclass(p));
|
|
+ unlock_user(p, arg1, 0);
|
|
+ break;
|
|
+
|
|
+ case TARGET_FREEBSD_NR_getloginclass:
|
|
+ if (!(p = lock_user_string(arg1)))
|
|
+ goto efault;
|
|
+ ret = get_errno(getloginclass(p, arg2));
|
|
+ unlock_user(p, arg1, 0);
|
|
+ break;
|
|
+
|
|
+ case TARGET_FREEBSD_NR_getrusage:
|
|
+ {
|
|
+ struct rusage rusage;
|
|
+ ret = get_errno(getrusage(arg1, &rusage));
|
|
+ if (!is_error(ret))
|
|
+ host_to_target_rusage(arg2, &rusage);
|
|
+ }
|
|
+ break;
|
|
+
|
|
+ case TARGET_FREEBSD_NR_wait4:
|
|
+ {
|
|
+ int status;
|
|
+ abi_long status_ptr = arg2;
|
|
+ struct rusage rusage, *rusage_ptr;
|
|
+ abi_ulong target_rusage = arg4;
|
|
+
|
|
+ if (target_rusage)
|
|
+ rusage_ptr = &rusage;
|
|
+ else
|
|
+ rusage_ptr = NULL;
|
|
+ ret = get_errno(wait4(arg1, &status, arg3, rusage_ptr));
|
|
+ if (!is_error(ret)) {
|
|
+ status = host_to_target_waitstatus(status);
|
|
+ if (put_user_s32(status, status_ptr))
|
|
+ goto efault;
|
|
+ if (target_rusage)
|
|
+ host_to_target_rusage(target_rusage, &rusage);
|
|
+ }
|
|
+ }
|
|
+ break;
|
|
+
|
|
+ case TARGET_FREEBSD_NR_accept:
|
|
+ ret = do_accept(arg1, arg2, arg3);
|
|
+ break;
|
|
+
|
|
+ case TARGET_FREEBSD_NR_bind:
|
|
+ ret = do_bind(arg1, arg2, arg3);
|
|
+ break;
|
|
+
|
|
+ case TARGET_FREEBSD_NR_connect:
|
|
+ ret = do_connect(arg1, arg2, arg3);
|
|
+ break;
|
|
+
|
|
+ case TARGET_FREEBSD_NR_getpeername:
|
|
+ ret = do_getpeername(arg1, arg2, arg3);
|
|
+ break;
|
|
+
|
|
+ case TARGET_FREEBSD_NR_getsockname:
|
|
+ ret = do_getsockname(arg1, arg2, arg3);
|
|
+ break;
|
|
+
|
|
+ case TARGET_FREEBSD_NR_getsockopt:
|
|
+ ret = do_getsockopt(arg1, arg2, arg3, arg4, arg5);
|
|
+ break;
|
|
+
|
|
+ case TARGET_FREEBSD_NR_setsockopt:
|
|
+ ret = do_setsockopt(arg1, arg2, arg3, arg4, arg5);
|
|
+ break;
|
|
+
|
|
+ case TARGET_FREEBSD_NR_listen:
|
|
+ ret = get_errno(listen(arg1, arg2));
|
|
+ break;
|
|
+
|
|
+ case TARGET_FREEBSD_NR_recvfrom:
|
|
+ ret = do_recvfrom(arg1, arg2, arg3, arg4, arg5, arg6);
|
|
+ break;
|
|
+
|
|
+ case TARGET_FREEBSD_NR_recvmsg:
|
|
+ ret = do_sendrecvmsg(arg1, arg2, arg3, 0);
|
|
+ break;
|
|
+
|
|
+ case TARGET_FREEBSD_NR_sendmsg:
|
|
+ ret = do_sendrecvmsg(arg1, arg2, arg3, 1);
|
|
+ break;
|
|
+
|
|
+ case TARGET_FREEBSD_NR_sendto:
|
|
+ ret = do_sendto(arg1, arg2, arg3, arg4, arg5, arg6);
|
|
+ break;
|
|
+
|
|
+ case TARGET_FREEBSD_NR_socket:
|
|
+ ret = get_errno(socket(arg1, arg2, arg3));
|
|
+ break;
|
|
+
|
|
+ case TARGET_FREEBSD_NR_socketpair:
|
|
+ ret = do_socketpair(arg1, arg2, arg3, arg4);
|
|
+ break;
|
|
+
|
|
+ case TARGET_FREEBSD_NR_getpriority:
|
|
+ /*
|
|
+ * Note that negative values are valid for getpriority, so we must
|
|
+ * differentiate based on errno settings.
|
|
+ */
|
|
+ errno = 0;
|
|
+ ret = getpriority(arg1, arg2);
|
|
+ if (ret == -1 && errno != 0) {
|
|
+ ret = -host_to_target_errno(errno);
|
|
+ break;
|
|
+ }
|
|
+ /* Return value is a biased priority to avoid negative numbers. */
|
|
+ ret = 20 - ret;
|
|
+ break;
|
|
+
|
|
+ case TARGET_FREEBSD_NR_setpriority:
|
|
+ ret = get_errno(setpriority(arg1, arg2, arg3));
|
|
+ break;
|
|
+
|
|
+ case TARGET_FREEBSD_NR_semget:
|
|
+ ret = get_errno(semget(arg1, arg2, arg3));
|
|
+ break;
|
|
+
|
|
+ case TARGET_FREEBSD_NR_semop:
|
|
+ ret = get_errno(do_semop(arg1, arg2, arg3));
|
|
+ break;
|
|
+
|
|
+ case TARGET_FREEBSD_NR___semctl:
|
|
+ ret = do_semctl(arg1, arg2, arg3, (union target_semun)(abi_ulong)arg4);
|
|
+ break;
|
|
+
|
|
+ case TARGET_FREEBSD_NR_msgctl:
|
|
+ ret = do_msgctl(arg1, arg2, arg3);
|
|
+ break;
|
|
+
|
|
+ case TARGET_FREEBSD_NR_msgrcv:
|
|
+ ret = do_msgrcv(arg1, arg2, arg3, arg4, arg5);
|
|
+ break;
|
|
+
|
|
+ case TARGET_FREEBSD_NR_msgsnd:
|
|
+ ret = do_msgsnd(arg1, arg2, arg3, arg4);
|
|
+ break;
|
|
+
|
|
+ case TARGET_FREEBSD_NR_shmget:
|
|
+ ret = get_errno(shmget(arg1, arg2, arg3));
|
|
+ break;
|
|
+
|
|
+ case TARGET_FREEBSD_NR_shmctl:
|
|
+ ret = do_shmctl(arg1, arg2, arg3);
|
|
+ break;
|
|
+
|
|
+ case TARGET_FREEBSD_NR_shmat:
|
|
+ ret = do_shmat(arg1, arg2, arg3);
|
|
+ break;
|
|
+
|
|
+ case TARGET_FREEBSD_NR_shmdt:
|
|
+ ret = do_shmdt(arg1);
|
|
+ break;
|
|
+
|
|
+ case TARGET_FREEBSD_NR_shm_open:
|
|
+ if (!(p = lock_user_string(arg1)))
|
|
+ goto efault;
|
|
+ ret = get_errno(shm_open(path(p),
|
|
+ target_to_host_bitmask(arg2, fcntl_flags_tbl),
|
|
+ arg3));
|
|
+ unlock_user(p, arg1, 0);
|
|
+ break;
|
|
+
|
|
+ case TARGET_FREEBSD_NR_shm_unlink:
|
|
+ if (!(p = lock_user_string(arg1)))
|
|
+ goto efault;
|
|
+ ret = get_errno(shm_unlink(p));
|
|
+ break;
|
|
+
|
|
+ case TARGET_FREEBSD_NR_getpid:
|
|
+ ret = get_errno(getpid());
|
|
+ break;
|
|
+
|
|
+ case TARGET_FREEBSD_NR_getppid:
|
|
+ ret = get_errno(getppid());
|
|
+ break;
|
|
+
|
|
+ case TARGET_FREEBSD_NR_getuid:
|
|
+ ret = get_errno(getuid());
|
|
+ break;
|
|
+
|
|
+ case TARGET_FREEBSD_NR_geteuid:
|
|
+ ret = get_errno(geteuid());
|
|
+ break;
|
|
+
|
|
+ case TARGET_FREEBSD_NR_getgid:
|
|
+ ret = get_errno(getgid());
|
|
+ break;
|
|
+
|
|
+ case TARGET_FREEBSD_NR_getegid:
|
|
+ ret = get_errno(getegid());
|
|
+ break;
|
|
+
|
|
+ case TARGET_FREEBSD_NR_setuid:
|
|
+ ret = get_errno(setuid(arg1));
|
|
+ break;
|
|
+
|
|
+ case TARGET_FREEBSD_NR_setgid:
|
|
+ ret = get_errno(setgid(arg1));
|
|
+ break;
|
|
+
|
|
+ case TARGET_FREEBSD_NR_setegid:
|
|
+ ret = get_errno(setegid(arg1));
|
|
+ break;
|
|
+
|
|
+ case TARGET_FREEBSD_NR_seteuid:
|
|
+ ret = get_errno(setegid(arg1));
|
|
+ break;
|
|
+
|
|
+ case TARGET_FREEBSD_NR_getpgrp:
|
|
+ ret = get_errno(getpgrp());
|
|
+ break;
|
|
+
|
|
+#ifdef TARGET_FREEBSD_NR_setpgrp
|
|
+ case TARGET_FREEBSD_NR_setpgrp:
|
|
+ ret = get_errno(setpgrp(arg1, arg2));
|
|
+ break;
|
|
+#endif
|
|
+
|
|
+ case TARGET_FREEBSD_NR_setreuid:
|
|
+ ret = get_errno(setreuid(arg1, arg2));
|
|
+ break;
|
|
+
|
|
+ case TARGET_FREEBSD_NR_setregid:
|
|
+ ret = get_errno(setregid(arg1, arg2));
|
|
+ break;
|
|
+
|
|
+ case TARGET_FREEBSD_NR_setresuid:
|
|
+ ret = get_errno(setresuid(arg1, arg2, arg3));
|
|
+ break;
|
|
+
|
|
+ case TARGET_FREEBSD_NR_setresgid:
|
|
+ ret = get_errno(setresgid(arg1, arg2, arg3));
|
|
+ break;
|
|
+
|
|
+ case TARGET_FREEBSD_NR_getresuid:
|
|
+ case TARGET_FREEBSD_NR_getresgid:
|
|
+ ret = unimplemented(num);
|
|
+ break;
|
|
+
|
|
+ case TARGET_FREEBSD_NR_setsid:
|
|
+ ret = get_errno(setsid());
|
|
+ break;
|
|
+
|
|
+ case TARGET_FREEBSD_NR_getsid:
|
|
+ ret = get_errno(getsid(arg1));
|
|
+ break;
|
|
+
|
|
+ case TARGET_FREEBSD_NR_setfib:
|
|
+ ret = get_errno(setfib(arg1));
|
|
+ break;
|
|
+
|
|
+ case TARGET_FREEBSD_NR___setugid:
|
|
+ ret = get_errno(__setugid(arg1));
|
|
+ break;
|
|
+
|
|
+ case TARGET_FREEBSD_NR_issetugid:
|
|
+ ret = get_errno(issetugid());
|
|
+ break;
|
|
+
|
|
+#ifdef TARGET_FREEBSD_NR_wait
|
|
+ case TARGET_FREEBSD_NR_wait:
|
|
+ ret = get_errno(wait());
|
|
+ break;
|
|
+#endif
|
|
+
|
|
+ case TARGET_FREEBSD_NR_fork:
|
|
+ ret = get_errno(do_fork(cpu_env, num, 0, NULL));
|
|
+ break;
|
|
+
|
|
+ case TARGET_FREEBSD_NR_rfork:
|
|
+ ret = get_errno(do_fork(cpu_env, num, arg1, NULL));
|
|
+ break;
|
|
+
|
|
+ case TARGET_FREEBSD_NR_vfork:
|
|
+ ret = get_errno(do_fork(cpu_env, num, 0, NULL));
|
|
+ break;
|
|
+
|
|
+ case TARGET_FREEBSD_NR_pdfork:
|
|
+ {
|
|
+ int pd;
|
|
+
|
|
+ ret = get_errno(do_fork(cpu_env, num, arg2, &pd));
|
|
+ if (put_user_s32(pd, arg1))
|
|
+ goto efault;
|
|
+ }
|
|
+ break;
|
|
+
|
|
+ case TARGET_FREEBSD_NR_kill:
|
|
+ ret = get_errno(kill(arg1, target_to_host_signal(arg2)));
|
|
+ break;
|
|
+
|
|
+#ifdef TARGET_FREEBSD_NR_killpg
|
|
+ case TARGET_FREEBSD_NR_killpg:
|
|
+ ret = get_errno(killpg(arg1, target_to_host_signal(arg2)));
|
|
+ break;
|
|
+#endif
|
|
+
|
|
+ case TARGET_FREEBSD_NR_sigaction:
|
|
+ {
|
|
+ struct target_sigaction *old_act, act, oact, *pact;
|
|
+
|
|
+ if (arg2) {
|
|
+ if (!lock_user_struct(VERIFY_READ, old_act, arg2, 1))
|
|
+ goto 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))
|
|
+ goto 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);
|
|
+ }
|
|
+ }
|
|
+ break;
|
|
+
|
|
+ case TARGET_FREEBSD_NR_sigprocmask:
|
|
+ {
|
|
+ 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:
|
|
+ ret = -TARGET_EINVAL;
|
|
+ goto fail;
|
|
+ }
|
|
+ if (!(p = lock_user(VERIFY_READ, arg2,
|
|
+ sizeof(target_sigset_t), 1)))
|
|
+ goto 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) {
|
|
+ if (!(p = lock_user(VERIFY_WRITE, arg3,
|
|
+ sizeof(target_sigset_t), 0)))
|
|
+ goto efault;
|
|
+ host_to_target_sigset(p, &oldset);
|
|
+ unlock_user(p, arg3, sizeof(target_sigset_t));
|
|
+ }
|
|
+ }
|
|
+ break;
|
|
+
|
|
+ case TARGET_FREEBSD_NR_sigpending:
|
|
+ {
|
|
+ sigset_t set;
|
|
+
|
|
+ ret = get_errno(sigpending(&set));
|
|
+ if (!is_error(ret)) {
|
|
+ if (!(p = lock_user(VERIFY_WRITE, arg1,
|
|
+ sizeof(target_sigset_t), 0)))
|
|
+ goto efault;
|
|
+ host_to_target_sigset(p, &set);
|
|
+ unlock_user(p, arg1, sizeof(target_sigset_t));
|
|
+ }
|
|
+ }
|
|
+ break;
|
|
+
|
|
+ case TARGET_FREEBSD_NR_sigsuspend:
|
|
+ {
|
|
+ sigset_t set;
|
|
+
|
|
+ if (!(p = lock_user(VERIFY_READ, arg1,
|
|
+ sizeof(target_sigset_t), 1)))
|
|
+ goto efault;
|
|
+ target_to_host_sigset(&set, p);
|
|
+ unlock_user(p, arg1, 0);
|
|
+ ret = get_errno(sigsuspend(&set));
|
|
+ }
|
|
+ break;
|
|
+
|
|
+ case TARGET_FREEBSD_NR_sigreturn:
|
|
+ ret = do_sigreturn(cpu_env, arg1);
|
|
+ break;
|
|
+
|
|
+#ifdef TARGET_FREEBSD_NR_sigvec
|
|
+ case TARGET_FREEBSD_NR_sigvec:
|
|
+ ret = unimplemented(num);
|
|
+ break;
|
|
+#endif
|
|
+#ifdef TARGET_FREEBSD_NR_sigblock
|
|
+ case TARGET_FREEBSD_NR_sigblock:
|
|
+ ret = unimplemented(num);
|
|
+ break;
|
|
+#endif
|
|
+#ifdef TARGET_FREEBSD_NR_sigsetmask
|
|
+ case TARGET_FREEBSD_NR_sigsetmask:
|
|
+ ret = unimplemented(num);
|
|
+ break;
|
|
+#endif
|
|
+#ifdef TARGET_FREEBSD_NR_sigstack
|
|
+ case TARGET_FREEBSD_NR_sigstack:
|
|
+ ret = unimplemented(num);
|
|
+ break;
|
|
+#endif
|
|
+
|
|
+ case TARGET_FREEBSD_NR_sigwait:
|
|
+ {
|
|
+ sigset_t set;
|
|
+ int sig;
|
|
+
|
|
+ if (!(p = lock_user(VERIFY_READ, arg1,
|
|
+ sizeof(target_sigset_t), 1)))
|
|
+ goto efault;
|
|
+ target_to_host_sigset(&set, p);
|
|
+ unlock_user(p, arg1, 0);
|
|
+ ret = get_errno(sigwait(&set, &sig));
|
|
+ if (!is_error(ret) && arg2) {
|
|
+ /* XXX */
|
|
+ }
|
|
+ }
|
|
+ break;
|
|
+
|
|
+ case TARGET_FREEBSD_NR_sigtimedwait:
|
|
+ {
|
|
+ sigset_t set;
|
|
+ struct timespec uts, *puts;
|
|
+ siginfo_t uinfo;
|
|
+
|
|
+ if (!(p = lock_user(VERIFY_READ, arg1,
|
|
+ sizeof(target_sigset_t), 1)))
|
|
+ goto efault;
|
|
+ target_to_host_sigset(&set, p);
|
|
+ unlock_user(p, arg1, 0);
|
|
+ if (arg3) {
|
|
+ puts = &uts;
|
|
+ target_to_host_timespec(puts, arg3);
|
|
+ } else {
|
|
+ puts = NULL;
|
|
+ }
|
|
+ ret = get_errno(sigtimedwait(&set, &uinfo, puts));
|
|
+ if (!is_error(ret) && arg2) {
|
|
+ if (!(p = lock_user(VERIFY_WRITE, arg2,
|
|
+ sizeof(target_siginfo_t), 0)))
|
|
+ goto efault;
|
|
+ host_to_target_siginfo(p, &uinfo);
|
|
+ unlock_user(p, arg2, sizeof(target_siginfo_t));
|
|
+ }
|
|
+ }
|
|
+ break;
|
|
+
|
|
+ case TARGET_FREEBSD_NR_sigwaitinfo:
|
|
+ {
|
|
+ sigset_t set;
|
|
+ siginfo_t uinfo;
|
|
+
|
|
+ if (!(p = lock_user(VERIFY_READ, arg1,
|
|
+ sizeof(target_sigset_t), 1)))
|
|
+ goto efault;
|
|
+ target_to_host_sigset(&set, p);
|
|
+ unlock_user(p, arg1, 0);
|
|
+ ret = get_errno(sigwaitinfo(&set, &uinfo));
|
|
+ if (!is_error(ret) && arg2) {
|
|
+ if (!(p = lock_user(VERIFY_WRITE, arg2,
|
|
+ sizeof(target_siginfo_t), 0)))
|
|
+ goto efault;
|
|
+ host_to_target_siginfo(p, &uinfo);
|
|
+ unlock_user(p, arg2, sizeof(target_siginfo_t));
|
|
+ }
|
|
+ }
|
|
+ break;
|
|
+
|
|
+ case TARGET_FREEBSD_NR_sigqueue:
|
|
+ {
|
|
+ union sigval value;
|
|
+
|
|
+ value.sival_ptr = (void *)(uintptr_t)arg3;
|
|
+ ret = get_errno(sigqueue(arg1, target_to_host_signal(arg2),
|
|
+ value));
|
|
+ }
|
|
+ break;
|
|
+
|
|
+ case TARGET_FREEBSD_NR_sigaltstack:
|
|
+ {
|
|
+
|
|
+ ret = do_sigaltstack(arg1, arg2,
|
|
+ get_sp_from_cpustate((CPUArchState *)cpu_env));
|
|
+ }
|
|
+
|
|
+#ifdef TARGET_FREEBSD_NR_aio_read
|
|
+ case TARGET_FREEBSD_NR_aio_read:
|
|
+#endif
|
|
+#ifdef TARGET_FREEBSD_NR_aio_write
|
|
+ case TARGET_FREEBSD_NR_aio_write:
|
|
+#endif
|
|
+#ifdef TARGET_FREEBSD_NR_aio_return
|
|
+ case TARGET_FREEBSD_NR_aio_return:
|
|
+#endif
|
|
+#ifdef TARGET_FREEBSD_NR_aio_suspend
|
|
+ case TARGET_FREEBSD_NR_aio_suspend:
|
|
+#endif
|
|
+#ifdef TARGET_FREEBSD_NR_aio_cancel
|
|
+ case TARGET_FREEBSD_NR_aio_cancel:
|
|
+#endif
|
|
+#ifdef TARGET_FREEBSD_NR_aio_error
|
|
+ case TARGET_FREEBSD_NR_aio_error:
|
|
+#endif
|
|
+#ifdef TARGET_FREEBSD_NR_aio_waitcomplete
|
|
+ case TARGET_FREEBSD_NR_aio_waitcomplete:
|
|
+#endif
|
|
+#ifdef TARGET_FREEBSD_NR_lio_listio
|
|
+ case TARGET_FREEBSD_NR_lio_listio:
|
|
+#endif
|
|
+
|
|
+ case TARGET_FREEBSD_NR_yield:
|
|
+ case TARGET_FREEBSD_NR_sched_setparam:
|
|
+ case TARGET_FREEBSD_NR_sched_getparam:
|
|
+ case TARGET_FREEBSD_NR_sched_setscheduler:
|
|
+ case TARGET_FREEBSD_NR_sched_getscheduler:
|
|
+ case TARGET_FREEBSD_NR_sched_yield:
|
|
+ case TARGET_FREEBSD_NR_sched_get_priority_max:
|
|
+ case TARGET_FREEBSD_NR_sched_get_priority_min:
|
|
+ case TARGET_FREEBSD_NR_sched_rr_get_interval:
|
|
+
|
|
+
|
|
+ case TARGET_FREEBSD_NR_reboot:
|
|
+ case TARGET_FREEBSD_NR_shutdown:
|
|
+
|
|
+ case TARGET_FREEBSD_NR_swapon:
|
|
+ case TARGET_FREEBSD_NR_swapoff:
|
|
+
|
|
+ case TARGET_FREEBSD_NR_pdkill:
|
|
+ case TARGET_FREEBSD_NR_pdgetpid:
|
|
+
|
|
+ case TARGET_FREEBSD_NR_thr_create:
|
|
+ case TARGET_FREEBSD_NR_thr_exit:
|
|
+ case TARGET_FREEBSD_NR_thr_self:
|
|
+ case TARGET_FREEBSD_NR_thr_suspend:
|
|
+ case TARGET_FREEBSD_NR_thr_wake:
|
|
+ case TARGET_FREEBSD_NR_thr_new:
|
|
+ case TARGET_FREEBSD_NR_thr_set_name:
|
|
+ case TARGET_FREEBSD_NR_thr_kill2:
|
|
+
|
|
+ case TARGET_FREEBSD_NR_getcontext:
|
|
+ case TARGET_FREEBSD_NR_setcontext:
|
|
+ case TARGET_FREEBSD_NR_swapcontext:
|
|
+
|
|
+ case TARGET_FREEBSD_NR_rtprio_thread:
|
|
+ case TARGET_FREEBSD_NR_cpuset:
|
|
+ case TARGET_FREEBSD_NR_cpuset_getid:
|
|
+ case TARGET_FREEBSD_NR_cpuset_setid:
|
|
+ case TARGET_FREEBSD_NR_cpuset_getaffinity:
|
|
+ case TARGET_FREEBSD_NR_cpuset_setaffinity:
|
|
+
|
|
+ case TARGET_FREEBSD_NR__umtx_lock:
|
|
+ case TARGET_FREEBSD_NR__umtx_unlock:
|
|
+
|
|
+ case TARGET_FREEBSD_NR_posix_fadvise:
|
|
+ case TARGET_FREEBSD_NR_posix_fallocate:
|
|
+
|
|
+ case TARGET_FREEBSD_NR_rctl_get_racct:
|
|
+ case TARGET_FREEBSD_NR_rctl_get_rules:
|
|
+ case TARGET_FREEBSD_NR_rctl_add_rule:
|
|
+ case TARGET_FREEBSD_NR_rctl_remove_rule:
|
|
+ case TARGET_FREEBSD_NR_rctl_get_limits:
|
|
+
|
|
+ case TARGET_FREEBSD_NR_ntp_adjtime:
|
|
+ case TARGET_FREEBSD_NR_ntp_gettime:
|
|
+
|
|
+#ifdef TARGET_FREEBSD_NR_getdomainname
|
|
+ case TARGET_FREEBSD_NR_getdomainname:
|
|
+#endif
|
|
+#ifdef TARGET_FREEBSD_NR_setdomainname
|
|
+ case TARGET_FREEBSD_NR_setdomainname:
|
|
+#endif
|
|
+#ifdef TARGET_FREEBSD_NR_uname
|
|
+ case TARGET_FREEBSD_NR_uname:
|
|
+#endif
|
|
+
|
|
+ case TARGET_FREEBSD_NR_sctp_peeloff:
|
|
+ case TARGET_FREEBSD_NR_sctp_generic_sendmsg:
|
|
+ case TARGET_FREEBSD_NR_sctp_generic_recvmsg:
|
|
+
|
|
+ case TARGET_FREEBSD_NR_getfh:
|
|
+ case TARGET_FREEBSD_NR_lgetfh:
|
|
+ case TARGET_FREEBSD_NR_fhstatfs:
|
|
+ case TARGET_FREEBSD_NR_fhopen:
|
|
+ case TARGET_FREEBSD_NR_fhstat:
|
|
+
|
|
+ case TARGET_FREEBSD_NR_getfsstat:
|
|
+ case TARGET_FREEBSD_NR_fstatfs:
|
|
+
|
|
+ case TARGET_FREEBSD_NR_modfnext:
|
|
+ case TARGET_FREEBSD_NR_modfind:
|
|
+ case TARGET_FREEBSD_NR_kldload:
|
|
+ case TARGET_FREEBSD_NR_kldunload:
|
|
+ case TARGET_FREEBSD_NR_kldunloadf:
|
|
+ case TARGET_FREEBSD_NR_kldfind:
|
|
+ case TARGET_FREEBSD_NR_kldnext:
|
|
+ case TARGET_FREEBSD_NR_kldstat:
|
|
+ case TARGET_FREEBSD_NR_kldfirstmod:
|
|
+ case TARGET_FREEBSD_NR_kldsym:
|
|
+
|
|
+ case TARGET_FREEBSD_NR_quotactl:
|
|
+#ifdef TARGET_FREEBSD_NR_quota
|
|
+ case TARGET_FREEBSD_NR_quota:
|
|
+#endif
|
|
+
|
|
+ case TARGET_FREEBSD_NR_adjtime:
|
|
+
|
|
+#ifdef TARGET_FREEBSD_NR_gethostid
|
|
+ case TARGET_FREEBSD_NR_gethostid:
|
|
+#endif
|
|
+#ifdef TARGET_FREEBSD_NR_gethostname
|
|
+ case TARGET_FREEBSD_NR_gethostname:
|
|
+#endif
|
|
+#ifdef TARGET_FREEBSD_NR_sethostname
|
|
+ case TARGET_FREEBSD_NR_sethostname:
|
|
+#endif
|
|
+
|
|
+ case TARGET_FREEBSD_NR_mincore:
|
|
+
|
|
+ case TARGET_FREEBSD_NR_vadvise:
|
|
+
|
|
+ case TARGET_FREEBSD_NR_sbrk:
|
|
+ case TARGET_FREEBSD_NR_sstk:
|
|
+
|
|
+#ifdef TARGET_FREEBSD_NR_getkerninfo
|
|
+ case TARGET_FREEBSD_NR_getkerninfo:
|
|
+#endif
|
|
+#ifdef TARGET_FREEBSD_NR_getpagesize
|
|
+ case TARGET_FREEBSD_NR_getpagesize:
|
|
+#endif
|
|
+
|
|
+ case TARGET_FREEBSD_NR_revoke:
|
|
+
|
|
+ case TARGET_FREEBSD_NR_profil:
|
|
+ case TARGET_FREEBSD_NR_ktrace:
|
|
+
|
|
+ case TARGET_FREEBSD_NR_jail:
|
|
+ case TARGET_FREEBSD_NR_jail_attach:
|
|
+ case TARGET_FREEBSD_NR_jail_get:
|
|
+ case TARGET_FREEBSD_NR_jail_set:
|
|
+ case TARGET_FREEBSD_NR_jail_remove:
|
|
+
|
|
+ case TARGET_FREEBSD_NR_cap_enter:
|
|
+ case TARGET_FREEBSD_NR_cap_getmode:
|
|
+
|
|
+ case TARGET_FREEBSD_NR_kenv:
|
|
+ case TARGET_FREEBSD_NR_uuidgen:
|
|
+
|
|
+ case TARGET_FREEBSD_NR___mac_get_proc:
|
|
+ case TARGET_FREEBSD_NR___mac_set_proc:
|
|
+ case TARGET_FREEBSD_NR___mac_get_fd:
|
|
+ case TARGET_FREEBSD_NR___mac_set_fd:
|
|
+ case TARGET_FREEBSD_NR___mac_get_file:
|
|
+ case TARGET_FREEBSD_NR___mac_set_file:
|
|
+ case TARGET_FREEBSD_NR___mac_get_link:
|
|
+ case TARGET_FREEBSD_NR___mac_set_link:
|
|
+ case TARGET_FREEBSD_NR_mac_syscall:
|
|
+
|
|
+ case TARGET_FREEBSD_NR_audit:
|
|
+ case TARGET_FREEBSD_NR_auditon:
|
|
+ case TARGET_FREEBSD_NR_getaudit:
|
|
+ case TARGET_FREEBSD_NR_setaudit:
|
|
+ case TARGET_FREEBSD_NR_getaudit_addr:
|
|
+ case TARGET_FREEBSD_NR_setaudit_addr:
|
|
+ case TARGET_FREEBSD_NR_auditctl:
|
|
+
|
|
+
|
|
+#ifdef TARGET_FREEBSD_NR_obreak
|
|
+ case TARGET_FREEBSD_NR_obreak:
|
|
+#endif
|
|
+ case TARGET_FREEBSD_NR_freebsd6_pread:
|
|
+ case TARGET_FREEBSD_NR_freebsd6_pwrite:
|
|
+ case TARGET_FREEBSD_NR_freebsd6_lseek:
|
|
+ case TARGET_FREEBSD_NR_freebsd6_truncate:
|
|
+ case TARGET_FREEBSD_NR_freebsd6_ftruncate:
|
|
+ case TARGET_FREEBSD_NR_sendfile:
|
|
+ case TARGET_FREEBSD_NR_ptrace:
|
|
+ case TARGET_FREEBSD_NR_utrace:
|
|
+ case TARGET_FREEBSD_NR_ioctl:
|
|
+ ret = unimplemented(num);
|
|
+ break;
|
|
+
|
|
+
|
|
default:
|
|
ret = get_errno(syscall(num, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8));
|
|
break;
|
|
diff --git a/bsd-user/syscall_defs.h b/bsd-user/syscall_defs.h
|
|
index 207ddee..ea1d25d 100644
|
|
--- a/bsd-user/syscall_defs.h
|
|
+++ b/bsd-user/syscall_defs.h
|
|
@@ -37,8 +37,6 @@
|
|
* @(#)signal.h 8.2 (Berkeley) 1/21/94
|
|
*/
|
|
|
|
-#define TARGET_NSIG 32 /* counting 0; could be 33 (mask is 1-32) */
|
|
-
|
|
#define TARGET_SIGHUP 1 /* hangup */
|
|
#define TARGET_SIGINT 2 /* interrupt */
|
|
#define TARGET_SIGQUIT 3 /* quit */
|
|
@@ -71,14 +69,21 @@
|
|
#define TARGET_SIGINFO 29 /* information request */
|
|
#define TARGET_SIGUSR1 30 /* user defined signal 1 */
|
|
#define TARGET_SIGUSR2 31 /* user defined signal 2 */
|
|
+#define TARGET_SIGTHR 32 /* reserved by thread library */
|
|
+#define TARGET_SIGLWP SIGTHR /* compatibility */
|
|
+#define TARGET_SIGLIBRT 33 /* reserved by the real-time library */
|
|
+#define TARGET_SIGRTMIN 65
|
|
+#define TARGET_SIGRTMAX 126
|
|
+#define TARGET_QEMU_ESIGRETURN 255 /* fake errno value for use by sigreturn */
|
|
+
|
|
|
|
/*
|
|
* Language spec says we must list exactly one parameter, even though we
|
|
* actually supply three. Ugh!
|
|
*/
|
|
-#define TARGET_SIG_DFL (void (*)(int))0
|
|
-#define TARGET_SIG_IGN (void (*)(int))1
|
|
-#define TARGET_SIG_ERR (void (*)(int))-1
|
|
+#define TARGET_SIG_DFL ((abi_long)0) /* default signal handling */
|
|
+#define TARGET_SIG_IGN ((abi_long)1) /* ignore signal */
|
|
+#define TARGET_SIG_ERR ((abi_long)-1) /* error return from signal */
|
|
|
|
#define TARGET_SA_ONSTACK 0x0001 /* take signal on signal stack */
|
|
#define TARGET_SA_RESTART 0x0002 /* restart system on signal return */
|
|
@@ -98,17 +103,503 @@
|
|
|
|
#define TARGET_BADSIG SIG_ERR
|
|
|
|
+/*
|
|
+ * sigaltstack controls
|
|
+ */
|
|
#define TARGET_SS_ONSTACK 0x0001 /* take signals on alternate stack */
|
|
-#define TARGET_SS_DISABLE 0x0004 /* disable taking signals on alternate stack */
|
|
+#define TARGET_SS_DISABLE 0x0004 /* disable taking signals on alternate
|
|
+ stack */
|
|
+
|
|
+#define TARGET_NSIG 128
|
|
+#define TARGET_NSIG_BPW (sizeof(uint32_t) * 8)
|
|
+#define TARGET_NSIG_WORDS (TARGET_NSIG / TARGET_NSIG_BPW)
|
|
+
|
|
+/*
|
|
+ * si_code values
|
|
+ * Digital reserves positive values for kernel-generated signals.
|
|
+ */
|
|
+
|
|
+/*
|
|
+ * SIGSEGV si_codes
|
|
+ */
|
|
+#define TARGET_SEGV_MAPERR (1) /* address not mapped to object */
|
|
+#define TARGET_SEGV_ACCERR (2) /* invalid permissions for mapped
|
|
+ object */
|
|
+/*
|
|
+ * SIGTRAP si_codes
|
|
+ */
|
|
+#define TARGET_TRAP_BRKPT (1) /* process beakpoint */
|
|
+#define TARGET_TRAP_TRACE (2) /* process trace trap */
|
|
|
|
+struct target_rlimit {
|
|
+ abi_ulong rlim_cur;
|
|
+ abi_ulong rlim_max;
|
|
+};
|
|
+
|
|
+#if defined(TARGET_ALPHA)
|
|
+#define TARGET_RLIM_INFINITY 0x7fffffffffffffffull
|
|
+#elif defined(TARGET_MIPS) || (defined(TARGET_SPARC) && TARGET_ABI_BITS == 32)
|
|
+#define TARGET_RLIM_INFINITY 0x7fffffffUL
|
|
+#else
|
|
+#define TARGET_RLIM_INFINITY ((abi_ulong)-1)
|
|
+#endif
|
|
+
|
|
+#define TARGET_RLIMIT_CPU 0
|
|
+#define TARGET_RLIMIT_FSIZE 1
|
|
+#define TARGET_RLIMIT_DATA 2
|
|
+#define TARGET_RLIMIT_STACK 3
|
|
+#define TARGET_RLIMIT_CORE 4
|
|
+#define TARGET_RLIMIT_RSS 5
|
|
+#define TARGET_RLIMIT_MEMLOCK 6
|
|
+#define TARGET_RLIMIT_NPROC 7
|
|
+#define TARGET_RLIMIT_NOFILE 8
|
|
+#define TARGET_RLIMIT_SBSIZE 9
|
|
+#define TARGET_RLIMIT_AS 10
|
|
+#define TARGET_RLIMIT_NPTS 11
|
|
+#define TARGET_RLIMIT_SWAP 12
|
|
+
|
|
+struct target_pollfd {
|
|
+ int fd; /* file descriptor */
|
|
+ short events; /* requested events */
|
|
+ short revents; /* returned events */
|
|
+};
|
|
+
|
|
+/*
|
|
+ * Constants used for fcntl(2).
|
|
+ */
|
|
+
|
|
+/* command values */
|
|
+#define TARGET_F_DUPFD 0
|
|
+#define TARGET_F_GETFD 1
|
|
+#define TARGET_F_SETFD 2
|
|
+#define TARGET_F_GETFL 3
|
|
+#define TARGET_F_SETFL 4
|
|
+#define TARGET_F_GETOWN 5
|
|
+#define TARGET_F_SETOWN 6
|
|
+#define TARGET_F_OGETLK 7
|
|
+#define TARGET_F_OSETLK 8
|
|
+#define TARGET_F_OSETLKW 9
|
|
+#define TARGET_F_DUP2FD 10
|
|
+#define TARGET_F_GETLK 11
|
|
+#define TARGET_F_SETLK 12
|
|
+#define TARGET_F_SETLKW 13
|
|
+#define TARGET_F_SETLK_REMOTE 14
|
|
+#define TARGET_F_READAHEAD 15
|
|
+#define TARGET_F_RDAHEAD 16
|
|
+
|
|
+#define TARGET_O_NONBLOCK 0x00000004
|
|
+#define TARGET_O_APPEND 0x00000008
|
|
+#define TARGET_O_ASYNC 0x00000040
|
|
+#define TARGET_O_DIRECT 0x00010000
|
|
+
|
|
+#define TARGET_SPARC_UTRAP_INSTALL 1
|
|
+#define TARGET_SPARC_SIGTRAMP_INSTALL 2
|
|
+
|
|
+#include "socket.h"
|
|
#include "errno_defs.h"
|
|
|
|
#include "freebsd/syscall_nr.h"
|
|
#include "netbsd/syscall_nr.h"
|
|
#include "openbsd/syscall_nr.h"
|
|
|
|
+struct target_flock {
|
|
+ unsigned long long l_start;
|
|
+ unsigned long long l_len;
|
|
+ int l_pid;
|
|
+ int l_sysid;
|
|
+ short l_type;
|
|
+ short l_whence;
|
|
+} QEMU_PACKED;
|
|
+
|
|
struct target_iovec {
|
|
abi_long iov_base; /* Starting address */
|
|
abi_long iov_len; /* Number of bytes */
|
|
};
|
|
|
|
+struct target_msghdr {
|
|
+ abi_long msg_name; /* Socket name */
|
|
+ int msg_namelen; /* Length of name */
|
|
+ abi_long msg_iov; /* Data blocks */
|
|
+ abi_long msg_iovlen; /* Number of blocks */
|
|
+ abi_long msg_control; /* Per protocol magic
|
|
+ (eg BSD file descriptor passing) */
|
|
+ abi_long msg_controllen; /* Length of cmsg list */
|
|
+ int msg_flags; /* flags on received message */
|
|
+};
|
|
+
|
|
+struct target_cmsghdr {
|
|
+ abi_long cmsg_len;
|
|
+ int cmsg_level;
|
|
+ int cmsg_type;
|
|
+};
|
|
+
|
|
+#define TARGET_CMSG_DATA(cmsg) \
|
|
+ ((unsigned char *) ((struct target_cmsghdr *) (cmsg) + 1))
|
|
+#define TARGET_CMSG_NXTHDR(mhdr, cmsg) __target_cmsg_nxthdr (mhdr, cmsg)
|
|
+#define TARGET_CMSG_ALIGN(len) (((len) + sizeof (abi_long) - 1) \
|
|
+ & (size_t) ~(sizeof (abi_long) - 1))
|
|
+#define TARGET_CMSG_SPACE(len) (TARGET_CMSG_ALIGN (len) \
|
|
+ + TARGET_CMSG_ALIGN (sizeof (struct target_cmsghdr)))
|
|
+#define TARGET_CMSG_LEN(len) \
|
|
+ (TARGET_CMSG_ALIGN (sizeof (struct target_cmsghdr)) + (len))
|
|
+
|
|
+static __inline__ struct target_cmsghdr *
|
|
+__target_cmsg_nxthdr (struct target_msghdr *__mhdr,
|
|
+ struct target_cmsghdr *__cmsg)
|
|
+{
|
|
+ struct target_cmsghdr *__ptr;
|
|
+
|
|
+ __ptr = (struct target_cmsghdr *)((unsigned char *) __cmsg +
|
|
+ TARGET_CMSG_ALIGN (tswapal(__cmsg->cmsg_len)));
|
|
+ if ((unsigned long)((char *)(__ptr+1) -
|
|
+ (char *)(size_t)tswapal(__mhdr->msg_control)) >
|
|
+ tswapal(__mhdr->msg_controllen))
|
|
+ /* No more entries. */
|
|
+ return ((struct target_cmsghdr *)0);
|
|
+ return (__cmsg);
|
|
+}
|
|
+
|
|
+struct target_sockaddr {
|
|
+ uint16_t sa_family;
|
|
+ uint8_t sa_data[14];
|
|
+};
|
|
+
|
|
+struct target_in_addr {
|
|
+ uint32_t s_addr; /* big endian */
|
|
+};
|
|
+
|
|
+
|
|
+struct target_timeval {
|
|
+ abi_long tv_sec;
|
|
+ abi_long tv_usec;
|
|
+};
|
|
+
|
|
+typedef abi_long target_clock_t;
|
|
+
|
|
+struct target_rusage {
|
|
+ struct target_timeval ru_utime; /* user time used */
|
|
+ struct target_timeval ru_stime; /* system time used */
|
|
+ abi_long ru_maxrss; /* maximum resident set size */
|
|
+ abi_long ru_ixrss; /* integral shared memory size */
|
|
+ abi_long ru_idrss; /* integral unshared data size */
|
|
+ abi_long ru_isrss; /* integral unshared stack size */
|
|
+ abi_long ru_minflt; /* page reclaims */
|
|
+ abi_long ru_majflt; /* page faults */
|
|
+ abi_long ru_nswap; /* swaps */
|
|
+ abi_long ru_inblock; /* block input operations */
|
|
+ abi_long ru_oublock; /* block output operations */
|
|
+ abi_long ru_msgsnd; /* messages sent */
|
|
+ abi_long ru_msgrcv; /* messages received */
|
|
+ abi_long ru_nsignals; /* signals received */
|
|
+ abi_long ru_nvcsw; /* voluntary context switches */
|
|
+ abi_long ru_nivcsw; /* involuntary context switches */
|
|
+};
|
|
+
|
|
+struct target_kevent {
|
|
+ abi_ulong ident;
|
|
+ short filter;
|
|
+ u_short flags;
|
|
+ u_int fflags;
|
|
+ abi_long data;
|
|
+ abi_ulong udata;
|
|
+} __packed;
|
|
+
|
|
+/*
|
|
+ * FreeBSD/arm uses a 64bits time_t, even in 32bits mode, so we have to
|
|
+ * add a special case here.
|
|
+ */
|
|
+#if defined(TARGET_ARM)
|
|
+typedef uint64_t target_freebsd_time_t;
|
|
+#else
|
|
+typedef long target_freebsd_time_t;
|
|
+#endif
|
|
+
|
|
+struct target_freebsd_timespec {
|
|
+ target_freebsd_time_t tv_sec; /* seconds */
|
|
+ abi_long tv_nsec; /* and nanoseconds */
|
|
+} __packed;
|
|
+
|
|
+struct target_freebsd_timeval {
|
|
+ target_freebsd_time_t tv_sec;
|
|
+ abi_long tv_usec;
|
|
+} __packed;
|
|
+
|
|
+struct target_freebsd_stat {
|
|
+ uint32_t st_dev; /* inode's device */
|
|
+ uint32_t st_ino; /* inode's number */
|
|
+ int16_t st_mode; /* inode protection mode */
|
|
+ int16_t st_nlink; /* number of hard links */
|
|
+ uint32_t st_uid; /* user ID of the file's owner */
|
|
+ uint32_t st_gid; /* group ID of the file's group */
|
|
+ uint32_t st_rdev; /* device type */
|
|
+ struct target_freebsd_timespec st_atim; /* time of last access */
|
|
+ struct target_freebsd_timespec st_mtim; /* time of last data modification */
|
|
+ struct target_freebsd_timespec st_ctim; /* time of last file status change */
|
|
+ int64_t st_size; /* file size, in bytes */
|
|
+ int64_t st_blocks; /* blocks allocated for file */
|
|
+ uint32_t st_blksize; /* optimal blocksize for I/O */
|
|
+ uint32_t st_flags; /* user defined flags for file */
|
|
+ __uint32_t st_gen; /* file generation number */
|
|
+ __int32_t st_lspare;
|
|
+ struct target_freebsd_timespec st_birthtim; /* time of file creation */
|
|
+ /*
|
|
+ * Explicitly pad st_birthtim to 16 bytes so that the size of
|
|
+ * struct stat is backwards compatible. We use bitfields instead
|
|
+ * of an array of chars so that this doesn't require a C99 compiler
|
|
+ * to compile if the size of the padding is 0. We use 2 bitfields
|
|
+ * to cover up to 64 bits on 32-bit machines. We assume that
|
|
+ * CHAR_BIT is 8...
|
|
+ */
|
|
+ unsigned int :(8 / 2) * (16 - (int)sizeof(struct timespec));
|
|
+ unsigned int :(8 / 2) * (16 - (int)sizeof(struct timespec));
|
|
+} __packed;
|
|
+
|
|
+int __getcwd(char *, size_t);
|
|
+
|
|
+struct target_sembuf {
|
|
+ unsigned short sem_num; /* semaphore # */
|
|
+ short sem_op; /* semaphore operation */
|
|
+ short sem_flg; /* operation flags */
|
|
+};
|
|
+
|
|
+union target_semun {
|
|
+ int val; /* value for SETVAL */
|
|
+ abi_ulong buf; /* buffer for IPC_STAT & IPC_SET */
|
|
+ abi_ulong array; /* array for GETALL & SETALL */
|
|
+};
|
|
+
|
|
+struct target_ipc_perm {
|
|
+ uint32_t cuid; /* creator user id */
|
|
+ uint32_t cgid; /* creator group id */
|
|
+ uint32_t uid; /* user id */
|
|
+ uint32_t gid; /* group id */
|
|
+ uint16_t mode; /* r/w permission */
|
|
+ uint16_t seq; /* sequence # */
|
|
+ abi_long key; /* user specified msg/sem/shm key */
|
|
+};
|
|
+
|
|
+struct target_msqid_ds {
|
|
+ struct target_ipc_perm msg_perm; /* msg queue permission bits */
|
|
+ abi_ulong msg_first; /* first message in the queue */
|
|
+ abi_ulong msg_last; /* last message in the queue */
|
|
+ abi_ulong msg_cbytes; /* # of bytes in use on the queue */
|
|
+ abi_ulong msg_qnum; /* number of msgs in the queue */
|
|
+ abi_ulong msg_qbytes; /* max # of bytes on the queue */
|
|
+ int32_t msg_lspid; /* pid of last msgsnd() */
|
|
+ int32_t msg_lrpid; /* pid of last msgrcv() */
|
|
+ abi_ulong msg_stime; /* time of last msgsnd() */
|
|
+ abi_ulong msg_rtime; /* time of last msgrcv() */
|
|
+ abi_ulong msg_ctime; /* time of last msgctl() */
|
|
+};
|
|
+
|
|
+struct target_msgbuf {
|
|
+ abi_long mtype; /* message type */
|
|
+ char mtext[1]; /* body of message */
|
|
+};
|
|
+
|
|
+struct target_semid_ds {
|
|
+ struct target_ipc_perm sem_perm; /* operation permission struct */
|
|
+ abi_ulong sem_base; /* pointer to first semaphore in set */
|
|
+ uint16_t sem_nsems; /* number of sems in set */
|
|
+ abi_ulong sem_otime; /* last operation time */
|
|
+ abi_ulong sem_ctime; /* times measured in secs */
|
|
+};
|
|
+
|
|
+struct target_shmid_ds {
|
|
+ struct target_ipc_perm shm_perm; /* peration permission structure */
|
|
+ abi_ulong shm_segsz; /* size of segment in bytes */
|
|
+ int32_t shm_lpid; /* process ID of last shared memory op */
|
|
+ int32_t shm_cpid; /* process ID of creator */
|
|
+ int32_t shm_nattch; /* number of current attaches */
|
|
+ abi_ulong shm_atime; /* time of last shmat() */
|
|
+ abi_ulong shm_dtime; /* time of last shmdt() */
|
|
+ abi_ulong shm_ctime; /* time of last change by shmctl() */
|
|
+};
|
|
+
|
|
+/* this struct defines a stack used during syscall handling */
|
|
+typedef struct target_sigaltstack {
|
|
+ abi_long ss_sp;
|
|
+ abi_ulong ss_size;
|
|
+ abi_long ss_flags;
|
|
+} target_stack_t;
|
|
+
|
|
+typedef struct {
|
|
+ uint32_t __bits[TARGET_NSIG_WORDS];
|
|
+} target_sigset_t;
|
|
+
|
|
+struct target_sigaction {
|
|
+ abi_ulong _sa_handler;
|
|
+ int32_t sa_flags;
|
|
+ target_sigset_t sa_mask;
|
|
+};
|
|
+
|
|
+union target_sigval {
|
|
+ int32_t sival_int;
|
|
+ abi_ulong sival_ptr;
|
|
+ int32_t sigval_int;
|
|
+ abi_ulong sigval_ptr;
|
|
+};
|
|
+
|
|
+typedef struct target_siginfo {
|
|
+ int32_t si_signo; /* signal number */
|
|
+ int32_t si_errno; /* errno association */
|
|
+ int32_t si_code; /* signal code */
|
|
+ int32_t si_pid; /* sending process */
|
|
+ int32_t si_uid; /* sender's ruid */
|
|
+ abi_ulong si_addr; /* faulting instruction */
|
|
+
|
|
+ union target_sigval si_value; /* signal value */
|
|
+
|
|
+ union {
|
|
+ struct {
|
|
+ int32_t _trapno; /* machine specific trap code */
|
|
+ } _fault;
|
|
+
|
|
+ /* POSIX.1b timers */
|
|
+ struct {
|
|
+ int32_t _timerid;
|
|
+ int32_t _overrun;
|
|
+ } _timer;
|
|
+
|
|
+ struct {
|
|
+ int32_t _mqd;
|
|
+ } _mesgp;
|
|
+
|
|
+ /* SIGPOLL */
|
|
+ struct {
|
|
+ int _band; /* POLL_IN, POLL_OUT, POLL_MSG */
|
|
+ } _poll;
|
|
+
|
|
+ struct {
|
|
+ abi_long __spare1__;
|
|
+ int32_t __spare2_[7];
|
|
+ } __spare__;
|
|
+ } _reason;
|
|
+} target_siginfo_t;
|
|
+
|
|
+#if defined(TARGET_MIPS)
|
|
+
|
|
+struct target_sigcontext {
|
|
+ target_sigset_t sc_mask; /* signal mask to retstore */
|
|
+ int32_t sc_onstack; /* sigstack state to restore */
|
|
+ abi_long sc_pc; /* pc at time of signal */
|
|
+ abi_long sc_reg[32]; /* processor regs 0 to 31 */
|
|
+ abi_long mullo, mulhi; /* mullo and mulhi registers */
|
|
+ int32_t sc_fpused; /* fp has been used */
|
|
+ abi_long sc_fpregs[33]; /* fp regs 0 to 31 & csr */
|
|
+ abi_long sc_fpc_eir; /* fp exception instr reg */
|
|
+ /* int32_t reserved[8]; */
|
|
+};
|
|
+
|
|
+typedef struct target_mcontext {
|
|
+ int32_t mc_onstack; /* sigstack state to restore */
|
|
+ abi_long mc_pc; /* pc at time of signal */
|
|
+ abi_long mc_regs[32]; /* process regs 0 to 31 */
|
|
+ abi_long sr; /* status register */
|
|
+ abi_long mullo, mulhi;
|
|
+ int32_t mc_fpused; /* fp has been used */
|
|
+ abi_long mc_fpregs[33]; /* fp regs 0 to 32 & csr */
|
|
+ abi_long mc_fpc_eir; /* fp exception instr reg */
|
|
+ abi_ulong mc_tls; /* pointer to TLS area */
|
|
+} target_mcontext_t;
|
|
+
|
|
+typedef struct target_ucontext {
|
|
+ target_sigset_t uc_sigmask;
|
|
+ target_mcontext_t uc_mcontext;
|
|
+ target_ulong uc_link;
|
|
+ target_stack_t uc_stack;
|
|
+ int32_t uc_flags;
|
|
+ int32_t __space__[8];
|
|
+} target_ucontext_t;
|
|
+
|
|
+struct target_sigframe {
|
|
+ abi_ulong sf_signum;
|
|
+ abi_ulong sf_siginfo; /* code or pointer to sf_si */
|
|
+ abi_ulong sf_ucontext; /* points to sf_uc */
|
|
+ abi_ulong sf_addr; /* undocumented 4th arg */
|
|
+ target_ucontext_t sf_uc; /* = *sf_uncontext */
|
|
+ target_siginfo_t sf_si; /* = *sf_siginfo (SA_SIGINFO case)*/
|
|
+ uint32_t __spare__[2];
|
|
+};
|
|
+
|
|
+#elif defined(TARGET_SPARC64)
|
|
+
|
|
+struct target_mcontext {
|
|
+ uint64_t mc_global[8];
|
|
+ uint64_t mc_out[8];
|
|
+ uint64_t mc_local[8];
|
|
+ uint64_t mc_in[8];
|
|
+ uint32_t mc_fp[64];
|
|
+} __aligned(64);
|
|
+
|
|
+typedef struct target_mcontext target_mcontext_t;
|
|
+
|
|
+typedef struct target_ucontext {
|
|
+ target_sigset_t uc_sigmask;
|
|
+ target_mcontext_t uc_mcontext;
|
|
+ target_ulong uc_link;
|
|
+ target_stack_t uc_stack;
|
|
+ int32_t uc_flags;
|
|
+ int32_t __space__[8];
|
|
+} target_ucontext_t;
|
|
+
|
|
+struct target_sigframe {
|
|
+ target_ucontext_t sf_uc;
|
|
+ target_siginfo_t sf_si;
|
|
+};
|
|
+
|
|
+#else
|
|
+
|
|
+typedef target_ulong target_mcontext_t; /* dummy */
|
|
+
|
|
+#endif
|
|
+
|
|
+/* XXX where did this come from?
|
|
+typedef struct target_ucontext {
|
|
+ target_ulong uc_flags;
|
|
+ target_ulong uc_link;
|
|
+ target_stack_t uc_stack;
|
|
+ target_mcontext_t uc_mcontext;
|
|
+ target_ulong uc_filer[80];
|
|
+ target_sigset_t uc_sigmask;
|
|
+} target_ucontext_t;
|
|
+*/
|
|
+
|
|
+
|
|
+#ifdef BSWAP_NEEDED
|
|
+static inline void
|
|
+tswap_sigset(target_sigset_t *d, const target_sigset_t *s)
|
|
+{
|
|
+ int i;
|
|
+
|
|
+ for(i = 0;i < TARGET_NSIG_WORDS; i++)
|
|
+ d->__bits[i] = tswapal(s->__bits[i]);
|
|
+}
|
|
+
|
|
+#else
|
|
+static inline void
|
|
+tswap_sigset(target_sigset_t *d, const target_sigset_t *s)
|
|
+{
|
|
+
|
|
+ *d = *s;
|
|
+}
|
|
+#endif
|
|
+
|
|
+/* XXX
|
|
+static inline void
|
|
+target_siginitset(target_sigset_t *d, abi_ulong set)
|
|
+{
|
|
+ int i;
|
|
+
|
|
+ d->sig[0] = set;
|
|
+ for(i = 1;i < TARGET_NSIG_WORDS; i++)
|
|
+ d->sig[i] = 0;
|
|
+}
|
|
+*/
|
|
+
|
|
+void host_to_target_sigset(target_sigset_t *d, const sigset_t *s);
|
|
+void target_to_host_sigset(sigset_t *d, const target_sigset_t *s);
|
|
+void host_to_target_old_sigset(abi_ulong *old_sigset, const sigset_t *sigset);
|
|
+void target_to_host_old_sigset(sigset_t *sigset, const abi_ulong *old_sigset);
|
|
+int do_sigaction(int sig, const struct target_sigaction *act,
|
|
+ struct target_sigaction *oact);
|
|
diff --git a/bsd-user/x86_64/target_signal.h b/bsd-user/x86_64/target_signal.h
|
|
index 659cd40..ea89f5a 100644
|
|
--- a/bsd-user/x86_64/target_signal.h
|
|
+++ b/bsd-user/x86_64/target_signal.h
|
|
@@ -3,17 +3,16 @@
|
|
|
|
#include "cpu.h"
|
|
|
|
-/* this struct defines a stack used during syscall handling */
|
|
-
|
|
-typedef struct target_sigaltstack {
|
|
- abi_ulong ss_sp;
|
|
- abi_long ss_flags;
|
|
- abi_ulong ss_size;
|
|
-} target_stack_t;
|
|
-
|
|
static inline abi_ulong get_sp_from_cpustate(CPUX86State *state)
|
|
{
|
|
return state->regs[R_ESP];
|
|
}
|
|
|
|
+#define TARGET_SS_ONSTACK 0x0001 /* take signal on alternate stack */
|
|
+#define TARGET_SS_DISABLE 0x0004 /* disable taking signals on
|
|
+ alternate stack */
|
|
+
|
|
+#define TARGET_MINSIGSTKSZ (512 * 4)
|
|
+#define TARGET_SIGSTKSZ (TARGET_MINSIGSTKSZ + 32768)
|
|
+
|
|
#endif /* TARGET_SIGNAL_H */
|
|
diff --git a/bsd-user/x86_64/target_vmparam.h b/bsd-user/x86_64/target_vmparam.h
|
|
new file mode 100644
|
|
index 0000000..aa5e0e0
|
|
--- /dev/null
|
|
+++ b/bsd-user/x86_64/target_vmparam.h
|
|
@@ -0,0 +1,28 @@
|
|
+#ifndef _TARGET_VMPARAM_H_
|
|
+#define _TARGET_VMPARAM_H_
|
|
+
|
|
+#if defined(__FreeBSD__)
|
|
+#define TARGET_VM_MAXUSER_ADDRESS (0x0000800000000000UL)
|
|
+
|
|
+#define TARGET_USRSTACK (TARGET_VM_MAXUSER_ADDRESS - TARGET_PAGE_SIZE)
|
|
+
|
|
+struct target_ps_strings {
|
|
+ abi_ulong ps_argvstr;
|
|
+ uint32_t ps_nargvstr;
|
|
+ abi_ulong ps_envstr;
|
|
+ uint32_t ps_nenvstr;
|
|
+};
|
|
+
|
|
+#define TARGET_SPACE_USRSPACE 4096
|
|
+#define TARGET_ARG_MAX 262144
|
|
+
|
|
+#define TARGET_PS_STRINGS (TARGET_USRSTACK - sizeof(struct target_ps_strings))
|
|
+
|
|
+#define TARGET_SZSIGCODE 0
|
|
+
|
|
+#else
|
|
+
|
|
+#define TARGET_USRSTACK 0
|
|
+#endif
|
|
+
|
|
+#endif /* _TARGET_VMPARAM_H_ */
|
|
diff --git a/configure b/configure
|
|
index 169b9bd..34eca43 100755
|
|
--- a/configure
|
|
+++ b/configure
|
|
@@ -1018,6 +1018,10 @@ x86_64-bsd-user \
|
|
sparc-bsd-user \
|
|
sparc64-bsd-user \
|
|
arm-bsd-user \
|
|
+armeb-bsd-user \
|
|
+mips-bsd-user \
|
|
+mipsel-bsd-user \
|
|
+mips64-bsd-user \
|
|
"
|
|
fi
|
|
|
|
diff --git a/default-configs/armeb-bsd-user.mak b/default-configs/armeb-bsd-user.mak
|
|
new file mode 100644
|
|
index 0000000..1b6fe65
|
|
--- /dev/null
|
|
+++ b/default-configs/armeb-bsd-user.mak
|
|
@@ -0,0 +1,3 @@
|
|
+# Default configuration for armeb-bsd-user
|
|
+
|
|
+CONFIG_GDBSTUB_XML=y
|
|
diff --git a/default-configs/mips-bsd-user.mak b/default-configs/mips-bsd-user.mak
|
|
new file mode 100644
|
|
index 0000000..3fb129a
|
|
--- /dev/null
|
|
+++ b/default-configs/mips-bsd-user.mak
|
|
@@ -0,0 +1 @@
|
|
+# Default configuration for mips-bsd-user
|
|
diff --git a/default-configs/mips64-bsd-user.mak b/default-configs/mips64-bsd-user.mak
|
|
new file mode 100644
|
|
index 0000000..d4e72a6
|
|
--- /dev/null
|
|
+++ b/default-configs/mips64-bsd-user.mak
|
|
@@ -0,0 +1 @@
|
|
+# Default configuration for mips64-bsd-user
|
|
diff --git a/default-configs/mipsel-bsd-user.mak b/default-configs/mipsel-bsd-user.mak
|
|
new file mode 100644
|
|
index 0000000..312b9d5
|
|
--- /dev/null
|
|
+++ b/default-configs/mipsel-bsd-user.mak
|
|
@@ -0,0 +1 @@
|
|
+# Default configuration for mipsel-bsd-user
|
|
diff --git a/target-mips/mips-defs.h b/target-mips/mips-defs.h
|
|
index bf094a3..030937c 100644
|
|
--- a/target-mips/mips-defs.h
|
|
+++ b/target-mips/mips-defs.h
|
|
@@ -10,8 +10,14 @@
|
|
|
|
#if defined(TARGET_MIPS64)
|
|
#define TARGET_LONG_BITS 64
|
|
-#define TARGET_PHYS_ADDR_SPACE_BITS 36
|
|
-#define TARGET_VIRT_ADDR_SPACE_BITS 42
|
|
+//#define TARGET_PHYS_ADDR_SPACE_BITS 36
|
|
+#define TARGET_PHYS_ADDR_SPACE_BITS 59
|
|
+# ifdef TARGET_ABI32
|
|
+# define TARGET_VIRT_ADDR_SPACE_BITS 32
|
|
+# else
|
|
+//# define TARGET_VIRT_ADDR_SPACE_BITS 42
|
|
+# define TARGET_VIRT_ADDR_SPACE_BITS 62
|
|
+# endif
|
|
#else
|
|
#define TARGET_LONG_BITS 32
|
|
#define TARGET_PHYS_ADDR_SPACE_BITS 36
|
|
diff --git a/user-exec.c b/user-exec.c
|
|
index b9ea9dd..9ad4858 100644
|
|
--- a/user-exec.c
|
|
+++ b/user-exec.c
|
|
@@ -34,11 +34,11 @@
|
|
#undef EDI
|
|
#undef EIP
|
|
#include <signal.h>
|
|
-#ifdef __linux__
|
|
+#if defined(__linux__) || defined(__FreeBSD__)
|
|
#include <sys/ucontext.h>
|
|
#endif
|
|
|
|
-//#define DEBUG_SIGNAL
|
|
+#define DEBUG_SIGNAL
|
|
|
|
static void exception_action(CPUArchState *env1)
|
|
{
|
|
@@ -58,6 +58,8 @@ void cpu_resume_from_signal(CPUArchState *env1, void *puc)
|
|
struct ucontext *uc = puc;
|
|
#elif defined(__OpenBSD__)
|
|
struct sigcontext *uc = puc;
|
|
+#elif defined(__NetBSD__) || defined(__FreeBSD__) || defined(__DragonFly__)
|
|
+ ucontext_t *uc = puc;
|
|
#endif
|
|
|
|
#ifndef CONFIG_TCG_PASS_AREG0
|
|
@@ -76,6 +78,8 @@ void cpu_resume_from_signal(CPUArchState *env1, void *puc)
|
|
#endif
|
|
#elif defined(__OpenBSD__)
|
|
sigprocmask(SIG_SETMASK, &uc->sc_mask, NULL);
|
|
+#elif defined(__NetBSD__) || defined(__FreeBSD__) || defined(__DragonFly__)
|
|
+ sigprocmask(SIG_SETMASK, &uc->uc_sigmask, NULL);
|
|
#endif
|
|
}
|
|
env1->exception_index = -1;
|