#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 ; ipage[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 ; ipage[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 #include +#include + #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; ie_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; ip_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 /* 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 #include #include +#include +#include +#include #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 + * -. 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 * * 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 #include #include +#include #include #include #include #include #include +#include #include +#include #include #include #include +#include #include +#include +#include +#include +#include +#ifdef __FreeBSD__ +#include +#include +#endif +#include +#include +#include +#include +#include #include +#include + #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_. */ -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; isem_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_. */ +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 -#ifdef __linux__ +#if defined(__linux__) || defined(__FreeBSD__) #include #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;