mirror of
https://git.freebsd.org/ports.git
synced 2025-06-27 07:30:32 -04:00
- Update emulators/qemu-devel to 1.4.0 with preliminary bsd-user patches. Thanx to: sson, cognet, and others for much improved bsd-user support - it now runs at least quite a few mips64 and single-threaded arm binaries, see: https://wiki.freebsd.org/QemuUserModeHowTo
2425 lines
72 KiB
Text
2425 lines
72 KiB
Text
diff --git a/bsd-user/elfload.c b/bsd-user/elfload.c
|
|
index f5f652f..8abb1dd 100644
|
|
--- a/bsd-user/elfload.c
|
|
+++ b/bsd-user/elfload.c
|
|
@@ -403,8 +403,11 @@ static inline void init_thread(struct target_pt_regs *regs, struct image_info *i
|
|
{
|
|
|
|
regs->cp0_status = 2 << CP0St_KSU;
|
|
- regs->regs[25] = regs->cp0_epc = infop->entry; /* t9 = pc = entry */
|
|
+ regs->regs[25] = regs->cp0_epc = infop->entry & ~3; /* t9 = pc = entry */
|
|
regs->regs[4] = regs->regs[29] = infop->start_stack; /* a0 = sp = start_stack */
|
|
+ regs->regs[5] = 0; /* a1 = 0 */
|
|
+ regs->regs[6] = 0; /* a2 = 0 */
|
|
+ regs->regs[7] = TARGET_PS_STRINGS; /* a3 = ps_strings */
|
|
}
|
|
|
|
#define USE_ELF_CORE_DUMP
|
|
@@ -765,7 +768,7 @@ static abi_ulong setup_arg_pages(abi_ulong p, struct bsd_binprm *bprm,
|
|
{
|
|
abi_ulong stack_hi_addr;
|
|
size_t execpath_len;
|
|
- abi_ulong destp;
|
|
+ abi_ulong destp, argvp, envp;
|
|
struct target_ps_strings ps_strs;
|
|
char canary[sizeof(abi_long) * 8];
|
|
char execpath[PATH_MAX];
|
|
@@ -808,6 +811,7 @@ static abi_ulong setup_arg_pages(abi_ulong p, struct bsd_binprm *bprm,
|
|
/* XXX - check return value of put_user_ual(). */
|
|
put_user_ual(TARGET_PAGE_SIZE, p);
|
|
|
|
+ argvp = p - TARGET_SPACE_USRSPACE;
|
|
p = destp = p - TARGET_SPACE_USRSPACE - TARGET_ARG_MAX;
|
|
|
|
/* XXX should check strlen(argv and envp strings) < TARGET_ARG_MAX */
|
|
@@ -816,31 +820,38 @@ static abi_ulong setup_arg_pages(abi_ulong p, struct bsd_binprm *bprm,
|
|
* Add argv strings. Note that the argv[] vectors are added by
|
|
* loader_build_argptr()
|
|
*/
|
|
+ envp = argvp + (bprm->argc + 2) * sizeof(abi_ulong);
|
|
+ ps_strs.ps_argvstr = tswapl(argvp);
|
|
+ ps_strs.ps_nargvstr = tswap32(bprm->argc);
|
|
// i = bprm->argc;
|
|
// while (i-- > 0) {
|
|
for (i = 0; i < bprm->argc; ++i) {
|
|
size_t len = strlen(bprm->argv[i]) + 1;
|
|
/* XXX - check return value of memcpy_to_target(). */
|
|
memcpy_to_target(destp, bprm->argv[i], len);
|
|
+ put_user_ual(destp, argvp);
|
|
+ argvp += sizeof(abi_ulong);
|
|
destp += len;
|
|
}
|
|
- ps_strs.ps_argvstr = tswapl(destp);
|
|
- ps_strs.ps_nargvstr = tswap32(bprm->argc);
|
|
+ put_user_ual(0, argvp);
|
|
|
|
/*
|
|
* Add env strings. Note that the envp[] vectors are added by
|
|
* loader_build_argptr().
|
|
*/
|
|
+ ps_strs.ps_envstr = tswapl(envp);
|
|
+ ps_strs.ps_nenvstr = tswap32(bprm->envc);
|
|
// i = bprm->envc;
|
|
// while(i-- > 0) {
|
|
for (i = 0; i < bprm->envc; ++i) {
|
|
size_t len = strlen(bprm->envp[i]) + 1;
|
|
/* XXX - check return value of memcpy_to_target(). */
|
|
memcpy_to_target(destp, bprm->envp[i], len);
|
|
+ put_user_ual(destp, envp);
|
|
+ envp += sizeof(abi_ulong);
|
|
destp += len;
|
|
}
|
|
- ps_strs.ps_envstr = tswapl(destp);
|
|
- ps_strs.ps_nenvstr = tswap32(bprm->envc);
|
|
+ put_user_ual(0, envp);
|
|
|
|
/* XXX - check return value of memcpy_to_target(). */
|
|
memcpy_to_target(stack_hi_addr - sizeof(ps_strs), &ps_strs,
|
|
@@ -1304,6 +1315,27 @@ static void load_symbols(struct elfhdr *hdr, int fd)
|
|
syminfos = s;
|
|
}
|
|
|
|
+/* Check the elf header and see if this a target elf binary. */
|
|
+int is_target_elf_binary(int fd)
|
|
+{
|
|
+ uint8_t buf[128];
|
|
+ struct elfhdr elf_ex;
|
|
+
|
|
+ if (lseek(fd, 0L, SEEK_SET) < 0)
|
|
+ return (0);
|
|
+ if (read(fd, buf, sizeof(buf)) < 0)
|
|
+ return (0);
|
|
+
|
|
+ elf_ex = *((struct elfhdr *)buf);
|
|
+ bswap_ehdr(&elf_ex);
|
|
+
|
|
+ if ((elf_ex.e_type != ET_EXEC && elf_ex.e_type != ET_DYN) ||
|
|
+ (! elf_check_arch(elf_ex.e_machine)))
|
|
+ return (0);
|
|
+ else
|
|
+ return (1);
|
|
+}
|
|
+
|
|
int load_elf_binary(struct bsd_binprm * bprm, struct target_pt_regs * regs,
|
|
struct image_info * info)
|
|
{
|
|
@@ -1424,13 +1456,10 @@ int load_elf_binary(struct bsd_binprm * bprm, struct target_pt_regs * regs,
|
|
/* JRP - Need to add X86 lib dir stuff here... */
|
|
|
|
if (strcmp(elf_interpreter,"/usr/lib/libc.so.1") == 0 ||
|
|
- strcmp(elf_interpreter,"/usr/lib/ld.so.1") == 0) {
|
|
+ strcmp(elf_interpreter,"/libexec/ld-elf.so.1") == 0) {
|
|
ibcs2_interpreter = 1;
|
|
}
|
|
|
|
-#if 0
|
|
- printf("Using ELF interpreter %s\n", path(elf_interpreter));
|
|
-#endif
|
|
if (retval >= 0) {
|
|
retval = open(path(elf_interpreter), O_RDONLY);
|
|
if(retval >= 0) {
|
|
diff --git a/bsd-user/freebsd/filio.h b/bsd-user/freebsd/filio.h
|
|
new file mode 100644
|
|
index 0000000..2269484
|
|
--- /dev/null
|
|
+++ b/bsd-user/freebsd/filio.h
|
|
@@ -0,0 +1,27 @@
|
|
+#ifndef _FREEBSD_FILIO_H_
|
|
+#define _FREEBSD_FILIO_H_
|
|
+
|
|
+/* see sys/filio.h */
|
|
+#define TARGET_FIOCLEX TARGET_IO('f', 1)
|
|
+#define TARGET_FIONCLEX TARGET_IO('f', 2)
|
|
+#define TARGET_FIONREAD TARGET_IOR('f', 127, int)
|
|
+#define TARGET_FIONBIO TARGET_IOW('f', 126, int)
|
|
+#define TARGET_FIOASYNC TARGET_IOW('f', 125, int)
|
|
+#define TARGET_FIOSETOWN TARGET_IOW('f', 124, int)
|
|
+#define TARGET_FIOGETOWN TARGET_IOR('f', 123, int)
|
|
+#define TARGET_FIODTYPE TARGET_IOR('f', 122, int)
|
|
+#define TARGET_FIOGETLBA TARGET_IOR('f', 121, int)
|
|
+
|
|
+struct target_fiodgname_arg {
|
|
+ int32_t len;
|
|
+ abi_ulong buf;
|
|
+};
|
|
+
|
|
+#define TARGET_FIODGNAME TARGET_IOW('f', 120, \
|
|
+ struct target_fiodgname_arg)
|
|
+#define TARGET_FIONWRITE TARGET_IOR('f', 119, int)
|
|
+#define TARGET_FIONSPACE TARGET_IOR('f', 118, int)
|
|
+#define TARGET_FIOSEEKDATA TARGET_IOWR('f', 97, off_t)
|
|
+#define TARGET_FIOSEEKHOLE TARGET_IOWR('f', 98, off_t)
|
|
+
|
|
+#endif /* !_FREEBSD_FILIO_H_ */
|
|
diff --git a/bsd-user/freebsd/ioctl.h b/bsd-user/freebsd/ioctl.h
|
|
deleted file mode 100644
|
|
index f83f6c1..0000000
|
|
--- a/bsd-user/freebsd/ioctl.h
|
|
+++ /dev/null
|
|
@@ -1,35 +0,0 @@
|
|
-#ifndef _FREEBSD_IOCTL_H_
|
|
-#define _FREEBSD_IOCTL_H_
|
|
-
|
|
-/* sys/ttycom.h tty(4) */
|
|
-IOCTL(TIOCSETD, IOC_W, MK_PTR(TYPE_INT))
|
|
-IOCTL(TIOCGETD, IOC_R, MK_PTR(TYPE_INT))
|
|
-IOCTL(TIOCSBRK, IOC_, TYPE_NULL)
|
|
-IOCTL(TIOCCBRK, IOC_, TYPE_NULL)
|
|
-IOCTL(TIOCSDTR, IOC_, TYPE_NULL)
|
|
-IOCTL(TIOCCDTR, IOC_, TYPE_NULL)
|
|
-IOCTL(TIOCGPGRP, IOC_R, MK_PTR(TYPE_INT))
|
|
-IOCTL(TIOCSPGRP, IOC_W, MK_PTR(TYPE_INT))
|
|
-IOCTL(TIOCGETA, IOC_R, MK_PTR(MK_STRUCT(STRUCT_termios)))
|
|
-IOCTL(TIOCSETA, IOC_W, MK_PTR(MK_STRUCT(STRUCT_termios)))
|
|
-IOCTL(TIOCSETAW, IOC_W, MK_PTR(MK_STRUCT(STRUCT_termios)))
|
|
-IOCTL(TIOCSETAF, IOC_W, MK_PTR(MK_STRUCT(STRUCT_termios)))
|
|
-IOCTL(TIOCOUTQ, IOC_R, MK_PTR(TYPE_INT))
|
|
-IOCTL(TIOCSTI, IOC_W, MK_PTR(TYPE_CHAR))
|
|
-IOCTL(TIOCNOTTY, IOC_, TYPE_NULL)
|
|
-IOCTL(TIOCSTOP, IOC_, TYPE_NULL)
|
|
-IOCTL(TIOCSTART, IOC_, TYPE_NULL)
|
|
-IOCTL(TIOCSCTTY, IOC_, TYPE_NULL)
|
|
-IOCTL(TIOCDRAIN, IOC_, TYPE_NULL)
|
|
-IOCTL(TIOCEXCL, IOC_, TYPE_NULL)
|
|
-IOCTL(TIOCNXCL, IOC_, TYPE_NULL)
|
|
-IOCTL(TIOCFLUSH, IOC_W, MK_PTR(TYPE_INT))
|
|
-IOCTL(TIOCGWINSZ, IOC_R, MK_PTR(MK_STRUCT(STRUCT_winsize)))
|
|
-IOCTL(TIOCSWINSZ, IOC_W, MK_PTR(MK_STRUCT(STRUCT_winsize)))
|
|
-IOCTL(TIOCCONS, IOC_W, MK_PTR(TYPE_INT))
|
|
-IOCTL(TIOCMSET, IOC_W, MK_PTR(TYPE_INT))
|
|
-IOCTL(TIOCMGET, IOC_R, MK_PTR(TYPE_INT))
|
|
-IOCTL(TIOCMBIS, IOC_W, MK_PTR(TYPE_INT))
|
|
-IOCTL(TIOCMBIC, IOC_W, MK_PTR(TYPE_INT))
|
|
-
|
|
-#endif
|
|
diff --git a/bsd-user/freebsd/ioctls.h b/bsd-user/freebsd/ioctls.h
|
|
new file mode 100644
|
|
index 0000000..85d3c41
|
|
--- /dev/null
|
|
+++ b/bsd-user/freebsd/ioctls.h
|
|
@@ -0,0 +1,47 @@
|
|
+
|
|
+/* sys/ttycom.h tty(4) */
|
|
+IOCTL(TIOCSETD, IOC_W, MK_PTR(TYPE_INT))
|
|
+IOCTL(TIOCGETD, IOC_R, MK_PTR(TYPE_INT))
|
|
+IOCTL(TIOCSBRK, IOC_, TYPE_NULL)
|
|
+IOCTL(TIOCCBRK, IOC_, TYPE_NULL)
|
|
+IOCTL(TIOCSDTR, IOC_, TYPE_NULL)
|
|
+IOCTL(TIOCCDTR, IOC_, TYPE_NULL)
|
|
+IOCTL(TIOCGPGRP, IOC_R, MK_PTR(TYPE_INT))
|
|
+IOCTL(TIOCSPGRP, IOC_W, MK_PTR(TYPE_INT))
|
|
+IOCTL(TIOCGETA, IOC_R, MK_PTR(MK_STRUCT(STRUCT_termios)))
|
|
+IOCTL(TIOCSETA, IOC_W, MK_PTR(MK_STRUCT(STRUCT_termios)))
|
|
+IOCTL(TIOCSETAW, IOC_W, MK_PTR(MK_STRUCT(STRUCT_termios)))
|
|
+IOCTL(TIOCSETAF, IOC_W, MK_PTR(MK_STRUCT(STRUCT_termios)))
|
|
+IOCTL(TIOCOUTQ, IOC_R, MK_PTR(TYPE_INT))
|
|
+IOCTL(TIOCSTI, IOC_W, MK_PTR(TYPE_CHAR))
|
|
+IOCTL(TIOCNOTTY, IOC_, TYPE_NULL)
|
|
+IOCTL(TIOCSTOP, IOC_, TYPE_NULL)
|
|
+IOCTL(TIOCSTART, IOC_, TYPE_NULL)
|
|
+IOCTL(TIOCSCTTY, IOC_, TYPE_NULL)
|
|
+IOCTL(TIOCDRAIN, IOC_, TYPE_NULL)
|
|
+IOCTL(TIOCEXCL, IOC_, TYPE_NULL)
|
|
+IOCTL(TIOCNXCL, IOC_, TYPE_NULL)
|
|
+IOCTL(TIOCFLUSH, IOC_W, MK_PTR(TYPE_INT))
|
|
+IOCTL(TIOCGWINSZ, IOC_R, MK_PTR(MK_STRUCT(STRUCT_winsize)))
|
|
+IOCTL(TIOCSWINSZ, IOC_W, MK_PTR(MK_STRUCT(STRUCT_winsize)))
|
|
+IOCTL(TIOCCONS, IOC_W, MK_PTR(TYPE_INT))
|
|
+IOCTL(TIOCMSET, IOC_W, MK_PTR(TYPE_INT))
|
|
+IOCTL(TIOCMGET, IOC_R, MK_PTR(TYPE_INT))
|
|
+IOCTL(TIOCMBIS, IOC_W, MK_PTR(TYPE_INT))
|
|
+IOCTL(TIOCMBIC, IOC_W, MK_PTR(TYPE_INT))
|
|
+
|
|
+/* sys/filio.h */
|
|
+IOCTL(FIOCLEX, IOC_, TYPE_NULL)
|
|
+IOCTL(FIONCLEX, IOC_, TYPE_NULL)
|
|
+IOCTL(FIONREAD, IOC_R, MK_PTR(TYPE_INT))
|
|
+IOCTL(FIONBIO, IOC_W, MK_PTR(TYPE_INT))
|
|
+IOCTL(FIOASYNC, IOC_W, MK_PTR(TYPE_INT))
|
|
+IOCTL(FIOSETOWN, IOC_W, MK_PTR(TYPE_INT))
|
|
+IOCTL(FIOGETOWN, IOC_R, MK_PTR(TYPE_INT))
|
|
+IOCTL(FIODTYPE, IOC_R, MK_PTR(TYPE_INT))
|
|
+IOCTL(FIOGETLBA, IOC_R, MK_PTR(TYPE_INT))
|
|
+IOCTL(FIODGNAME, IOC_R, MK_PTR(STRUCT_fiodgname_arg))
|
|
+IOCTL(FIONWRITE, IOC_R, MK_PTR(TYPE_INT))
|
|
+IOCTL(FIONSPACE, IOC_R, MK_PTR(TYPE_INT))
|
|
+IOCTL(FIOSEEKDATA, IOC_RW, MK_PTR(TYPE_ULONG))
|
|
+IOCTL(FIOSEEKHOLE, IOC_RW, MK_PTR(TYPE_ULONG))
|
|
diff --git a/bsd-user/freebsd/strace.list b/bsd-user/freebsd/strace.list
|
|
index c66dcfa..8270c37 100644
|
|
--- a/bsd-user/freebsd/strace.list
|
|
+++ b/bsd-user/freebsd/strace.list
|
|
@@ -1,7 +1,19 @@
|
|
+{ TARGET_FREEBSD_NR___acl_aclcheck_fd, "__acl_get_fd", "%s(%d, %d, %#x)", NULL, NULL },
|
|
+{ TARGET_FREEBSD_NR___acl_aclcheck_file, "__acl_get_file", "%s(\"%s\", %d, %#x)", NULL, NULL },
|
|
+{ TARGET_FREEBSD_NR___acl_aclcheck_link, "__acl_get_link", "%s(\"%s\", %d, %#x)", NULL, NULL },
|
|
+{ TARGET_FREEBSD_NR___acl_delete_fd, "__acl_delete_fd", "%s(%d, %d)", NULL, NULL },
|
|
+{ TARGET_FREEBSD_NR___acl_delete_file, "__acl_delete_file", "%s(\"%s\", %d)", NULL, NULL },
|
|
+{ TARGET_FREEBSD_NR___acl_delete_link, "__acl_delete_link", "%s(\"%s\", %d)", NULL, NULL },
|
|
+{ TARGET_FREEBSD_NR___acl_get_fd, "__acl_get_fd", "%s(\"%s\", %d, %#x)", NULL, NULL },
|
|
+{ TARGET_FREEBSD_NR___acl_get_file, "__acl_get_file", "%s(\"%s\", %d, %#x)", NULL, NULL },
|
|
+{ TARGET_FREEBSD_NR___acl_get_link, "__acl_get_link", "%s(\"%s\", %d, %#x)", NULL, NULL },
|
|
+{ TARGET_FREEBSD_NR___acl_set_fd, "__acl_get_fd", "%s(\"%s\", %d, %#x)", NULL, NULL },
|
|
+{ TARGET_FREEBSD_NR___acl_set_file, "__acl_get_file", "%s(\"%s\", %d, %#x)", NULL, NULL },
|
|
+{ TARGET_FREEBSD_NR___acl_set_link, "__acl_get_link", "%s(\"%s\", %d, %#x)", NULL, NULL },
|
|
{ TARGET_FREEBSD_NR___getcwd, "__getcwd", NULL, NULL, NULL },
|
|
{ TARGET_FREEBSD_NR___semctl, "__semctl", NULL, NULL, NULL },
|
|
{ TARGET_FREEBSD_NR___syscall, "__syscall", NULL, NULL, NULL },
|
|
-{ TARGET_FREEBSD_NR___sysctl, "__sysctl", NULL, NULL, NULL },
|
|
+{ TARGET_FREEBSD_NR___sysctl, "__sysctl", NULL, print_sysctl, NULL },
|
|
{ TARGET_FREEBSD_NR__umtx_op, "_umtx_op", "%s(%#x, %d, %d, %#x, %#x)", NULL, NULL },
|
|
{ TARGET_FREEBSD_NR_accept, "accept", "%s(%d,%#x,%#x)", NULL, NULL },
|
|
{ TARGET_FREEBSD_NR_access, "access", "%s(\"%s\",%#o)", NULL, NULL },
|
|
@@ -23,19 +35,34 @@
|
|
{ TARGET_FREEBSD_NR_dup2, "dup2", NULL, NULL, NULL },
|
|
{ TARGET_FREEBSD_NR_execve, "execve", NULL, print_execve, NULL },
|
|
{ TARGET_FREEBSD_NR_exit, "exit", "%s(%d)\n", NULL, NULL },
|
|
+{ TARGET_FREEBSD_NR_extattrctl, "extattrctl", "%s(\"%s\", %d, \"%s\", %d, \"%s\"", NULL, NULL },
|
|
+{ TARGET_FREEBSD_NR_extattr_delete_fd, "extattr_delete_fd", "%s(%d, %d, \"%s\")", NULL, NULL },
|
|
+{ TARGET_FREEBSD_NR_extattr_delete_file, "extattr_delete_file", "%s(\"%s\", %d, \"%s\")", NULL, NULL },
|
|
+{ TARGET_FREEBSD_NR_extattr_delete_link, "extattr_delete_link", "%s(\"%s\", %d, \"%s\")", NULL, NULL },
|
|
+{ TARGET_FREEBSD_NR_extattr_get_fd, "extattr_get_fd", "%s(%d, %d, \"%s\", %#x, %d)", NULL, NULL },
|
|
+{ TARGET_FREEBSD_NR_extattr_get_file, "extattr_get_file", "%s(\"%s\", %d, \"%s\", %#x, %d)", NULL, NULL },
|
|
+{ TARGET_FREEBSD_NR_extattr_get_file, "extattr_get_link", "%s(\"%s\", %d, \"%s\", %#x, %d)", NULL, NULL },
|
|
+{ TARGET_FREEBSD_NR_extattr_list_fd, "extattr_list_fd", "%s(%d, %d, %#x, %d)", NULL, NULL },
|
|
+{ TARGET_FREEBSD_NR_extattr_list_file, "extattr_list_file", "%s(\"%s\", %#x, %d)", NULL, NULL },
|
|
+{ TARGET_FREEBSD_NR_extattr_list_link, "extattr_list_link", "%s(\"%s\", %d, %#x, %d)", NULL, NULL },
|
|
+{ TARGET_FREEBSD_NR_extattr_set_fd, "extattr_set_fd", "%s(%d, %d, \"%s\", %#x, %d)", NULL, NULL },
|
|
+{ TARGET_FREEBSD_NR_extattr_set_file, "extattr_set_file", "%s(\"%s\", %d, \"%s\", %#x, %d)", NULL, NULL },
|
|
+{ TARGET_FREEBSD_NR_extattr_set_link, "extattr_set_link", "%s(\"%s\", %d, \"%s\", %#x, %d)", NULL, NULL },
|
|
{ TARGET_FREEBSD_NR_fchdir, "fchdir", NULL, NULL, NULL },
|
|
{ TARGET_FREEBSD_NR_fchflags, "fchflags", NULL, NULL, NULL },
|
|
{ TARGET_FREEBSD_NR_fchmod, "fchmod", "%s(%d,%#o)", NULL, NULL },
|
|
{ TARGET_FREEBSD_NR_fchown, "fchown", "%s(\"%s\",%d,%d)", NULL, NULL },
|
|
{ TARGET_FREEBSD_NR_fcntl, "fcntl", NULL, NULL, NULL },
|
|
+{ TARGET_FREEBSD_NR_fexecve, "fexecve", NULL, print_execve, NULL },
|
|
{ TARGET_FREEBSD_NR_fhopen, "fhopen", NULL, NULL, NULL },
|
|
{ TARGET_FREEBSD_NR_fhstat, "fhstat", NULL, NULL, NULL },
|
|
{ TARGET_FREEBSD_NR_fhstatfs, "fhstatfs", NULL, NULL, NULL },
|
|
{ TARGET_FREEBSD_NR_flock, "flock", NULL, NULL, NULL },
|
|
{ TARGET_FREEBSD_NR_fork, "fork", "%s()", NULL, NULL },
|
|
{ TARGET_FREEBSD_NR_fpathconf, "fpathconf", NULL, NULL, NULL },
|
|
-{ TARGET_FREEBSD_NR_fstat, "fstat", "%s(%d,%p)", NULL, NULL },
|
|
-{ TARGET_FREEBSD_NR_fstatfs, "fstatfs", "%s(%d,%p)", NULL, NULL },
|
|
+{ TARGET_FREEBSD_NR_fstat, "fstat", "%s(%d,%#x)", NULL, NULL },
|
|
+{ TARGET_FREEBSD_NR_fstatat, "fstatat", "%s(%d,\"%s\", %#x)", NULL, NULL },
|
|
+{ TARGET_FREEBSD_NR_fstatfs, "fstatfs", "%s(%d,%#x)", NULL, NULL },
|
|
{ TARGET_FREEBSD_NR_fsync, "fsync", NULL, NULL, NULL },
|
|
{ TARGET_FREEBSD_NR_ftruncate, "ftruncate", NULL, NULL, NULL },
|
|
{ TARGET_FREEBSD_NR_futimes, "futimes", NULL, NULL, NULL },
|
|
@@ -65,7 +92,7 @@
|
|
{ TARGET_FREEBSD_NR_getsockopt, "getsockopt", NULL, NULL, NULL },
|
|
{ TARGET_FREEBSD_NR_gettimeofday, "gettimeofday", NULL, NULL, NULL },
|
|
{ TARGET_FREEBSD_NR_getuid, "getuid", "%s()", NULL, NULL },
|
|
-{ TARGET_FREEBSD_NR_ioctl, "ioctl", NULL, NULL, NULL },
|
|
+{ TARGET_FREEBSD_NR_ioctl, "ioctl", NULL, print_ioctl, NULL },
|
|
{ TARGET_FREEBSD_NR_issetugid, "issetugid", "%s()", NULL, NULL },
|
|
{ TARGET_FREEBSD_NR_kevent, "kevent", NULL, NULL, NULL },
|
|
{ TARGET_FREEBSD_NR_kill, "kill", NULL, NULL, NULL },
|
|
@@ -74,6 +101,7 @@
|
|
{ TARGET_FREEBSD_NR_lchown, "lchown", NULL, NULL, NULL },
|
|
{ TARGET_FREEBSD_NR_link, "link", "%s(\"%s\",\"%s\")", NULL, NULL },
|
|
{ TARGET_FREEBSD_NR_listen, "listen", NULL, NULL, NULL },
|
|
+{ TARGET_FREEBSD_NR_lpathconf, "lpathconf", "%s(\"%s\", %d)", NULL, NULL },
|
|
{ TARGET_FREEBSD_NR_lseek, "lseek", NULL, NULL, NULL },
|
|
{ TARGET_FREEBSD_NR_lstat, "lstat", "%s(\"%s\",%p)", NULL, NULL },
|
|
{ TARGET_FREEBSD_NR_madvise, "madvise", NULL, NULL, NULL },
|
|
@@ -98,7 +126,9 @@
|
|
{ TARGET_FREEBSD_NR_nanosleep, "nanosleep", NULL, NULL, NULL },
|
|
{ TARGET_FREEBSD_NR_nfssvc, "nfssvc", NULL, NULL, NULL },
|
|
{ TARGET_FREEBSD_NR_open, "open", "%s(\"%s\",%#x,%#o)", NULL, NULL },
|
|
+{ TARGET_FREEBSD_NR_openat, "openat", "%s(%d, \"%s\",%#x,%#o)", NULL, NULL },
|
|
{ TARGET_FREEBSD_NR_pathconf, "pathconf", NULL, NULL, NULL },
|
|
+{ TARGET_FREEBSD_NR_pathconf, "pathconf", "%s(\"%s\", %d)", NULL, NULL },
|
|
{ TARGET_FREEBSD_NR_pipe, "pipe", NULL, NULL, NULL },
|
|
{ TARGET_FREEBSD_NR_poll, "poll", NULL, NULL, NULL },
|
|
{ TARGET_FREEBSD_NR_pread, "pread", NULL, NULL, NULL },
|
|
@@ -162,7 +192,7 @@
|
|
{ TARGET_FREEBSD_NR_statfs, "statfs", "%s(\"%s\",%p)", NULL, NULL },
|
|
{ TARGET_FREEBSD_NR_symlink, "symlink", "%s(\"%s\",\"%s\")", NULL, NULL },
|
|
{ TARGET_FREEBSD_NR_sync, "sync", NULL, NULL, NULL },
|
|
-{ TARGET_FREEBSD_NR_sysarch, "sysarch", NULL, NULL, NULL },
|
|
+{ TARGET_FREEBSD_NR_sysarch, "sysarch", NULL, print_sysarch, NULL },
|
|
{ TARGET_FREEBSD_NR_syscall, "syscall", NULL, NULL, NULL },
|
|
{ TARGET_FREEBSD_NR_thr_create, "thr_create", NULL, NULL, NULL },
|
|
{ TARGET_FREEBSD_NR_thr_exit, "thr_exit", NULL, NULL, NULL },
|
|
diff --git a/bsd-user/freebsd/syscall_types.h b/bsd-user/freebsd/syscall_types.h
|
|
index 6e43400..60b9288 100644
|
|
--- a/bsd-user/freebsd/syscall_types.h
|
|
+++ b/bsd-user/freebsd/syscall_types.h
|
|
@@ -1,8 +1,7 @@
|
|
-#ifndef _FREEBSD_SYSCALL_TYPES_H_
|
|
-#define _FREEBSD_SYSCALL_TYPES_H_
|
|
|
|
STRUCT_SPECIAL(termios)
|
|
|
|
STRUCT(winsize, TYPE_SHORT, TYPE_SHORT, TYPE_SHORT, TYPE_SHORT)
|
|
|
|
-#endif
|
|
+STRUCT(fiodgname_arg, TYPE_INT, TYPE_PTRVOID)
|
|
+
|
|
diff --git a/bsd-user/main.c b/bsd-user/main.c
|
|
index 32bd3e5..bb614de 100644
|
|
--- a/bsd-user/main.c
|
|
+++ b/bsd-user/main.c
|
|
@@ -2,6 +2,7 @@
|
|
* qemu user main
|
|
*
|
|
* Copyright (c) 2003-2008 Fabrice Bellard
|
|
+ * Copyright (c) 2012-2013 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
|
|
@@ -25,6 +26,7 @@
|
|
#include <machine/trap.h>
|
|
#include <sys/types.h>
|
|
#include <sys/mman.h>
|
|
+#include <sys/sysctl.h>
|
|
|
|
#include "qemu.h"
|
|
#include "qemu-common.h"
|
|
@@ -58,6 +60,36 @@ enum BSDType bsd_type;
|
|
by remapping the process stack directly at the right place */
|
|
unsigned long x86_stack_size = 512 * 1024;
|
|
|
|
+static void save_proc_pathname(void);
|
|
+char qemu_proc_pathname[PATH_MAX];
|
|
+
|
|
+#ifdef __FreeBSD__
|
|
+static void
|
|
+save_proc_pathname(void)
|
|
+{
|
|
+ int mib[4];
|
|
+ size_t len;
|
|
+
|
|
+ mib[0] = CTL_KERN;
|
|
+ mib[1] = KERN_PROC;
|
|
+ mib[2] = KERN_PROC_PATHNAME;
|
|
+ mib[3] = -1;
|
|
+
|
|
+ len = sizeof(qemu_proc_pathname);
|
|
+
|
|
+ if (sysctl(mib, 4, qemu_proc_pathname, &len, NULL, 0))
|
|
+ perror("sysctl");
|
|
+}
|
|
+
|
|
+#else
|
|
+
|
|
+static void
|
|
+save_proc_pathname(void)
|
|
+{
|
|
+}
|
|
+
|
|
+#endif /* !__FreeBSD__ */
|
|
+
|
|
void gemu_log(const char *fmt, ...)
|
|
{
|
|
va_list ap;
|
|
@@ -1496,6 +1528,8 @@ int main(int argc, char **argv)
|
|
if (argc <= 1)
|
|
usage();
|
|
|
|
+ save_proc_pathname();
|
|
+
|
|
module_call_init(MODULE_INIT_QOM);
|
|
|
|
if ((envlist = envlist_create()) == NULL) {
|
|
diff --git a/bsd-user/mips64/target_signal.h b/bsd-user/mips64/target_signal.h
|
|
index e9c8a9f..c592136 100644
|
|
--- a/bsd-user/mips64/target_signal.h
|
|
+++ b/bsd-user/mips64/target_signal.h
|
|
@@ -65,13 +65,7 @@ set_sigtramp_args(CPUMIPSState *regs, int sig, struct target_sigframe *frame,
|
|
abi_ulong frame_addr, struct target_sigaction *ka)
|
|
{
|
|
|
|
- frame->sf_signum = sig;
|
|
- frame->sf_siginfo = 0;
|
|
- frame->sf_ucontext = 0;
|
|
-
|
|
- frame->sf_si.si_signo = sig;
|
|
- frame->sf_si.si_code = TARGET_SA_SIGINFO;
|
|
- frame->sf_si.si_addr = regs->CP0_BadVAddr;
|
|
+ /* frame->sf_si.si_addr = regs->CP0_BadVAddr; */
|
|
|
|
/*
|
|
* Arguments to signal handler:
|
|
@@ -86,6 +80,8 @@ set_sigtramp_args(CPUMIPSState *regs, int sig, struct target_sigframe *frame,
|
|
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;
|
|
diff --git a/bsd-user/qemu.h b/bsd-user/qemu.h
|
|
index d9c9934..110b54e 100644
|
|
--- a/bsd-user/qemu.h
|
|
+++ b/bsd-user/qemu.h
|
|
@@ -64,15 +64,15 @@ struct image_info {
|
|
|
|
#define MAX_SIGQUEUE_SIZE 1024
|
|
|
|
-struct sigqueue {
|
|
- struct sigqueue *next;
|
|
+struct qemu_sigqueue {
|
|
+ struct qemu_sigqueue *next;
|
|
target_siginfo_t info;
|
|
};
|
|
|
|
struct emulated_sigtable {
|
|
int pending; /* true if signal is pending */
|
|
- struct sigqueue *first;
|
|
- struct sigqueue info; /* in order to always have memory for the
|
|
+ struct qemu_sigqueue *first;
|
|
+ struct qemu_sigqueue info; /* in order to always have memory for the
|
|
first signal, we put it here */
|
|
};
|
|
|
|
@@ -95,8 +95,8 @@ typedef struct TaskState {
|
|
struct bsd_binprm *bprm;
|
|
|
|
struct emulated_sigtable sigtab[TARGET_NSIG];
|
|
- struct sigqueue sigqueue_table[MAX_SIGQUEUE_SIZE]; /* siginfo queue */
|
|
- struct sigqueue *first_free; /* first free siginfo queue entry */
|
|
+ struct qemu_sigqueue sigqueue_table[MAX_SIGQUEUE_SIZE]; /* siginfo queue */
|
|
+ struct qemu_sigqueue *first_free; /* first free siginfo queue entry */
|
|
int signal_pending; /* non zero if a signal may be pending */
|
|
|
|
uint8_t stack[0];
|
|
@@ -146,6 +146,7 @@ int load_elf_binary(struct bsd_binprm * bprm, struct target_pt_regs * regs,
|
|
struct image_info * info);
|
|
int load_flt_binary(struct bsd_binprm * bprm, struct target_pt_regs * regs,
|
|
struct image_info * info);
|
|
+int is_target_elf_binary(int fd);
|
|
|
|
void target_set_brk(abi_ulong new_brk);
|
|
abi_long do_brk(abi_ulong new_brk);
|
|
@@ -222,6 +223,7 @@ void mmap_fork_end(int child);
|
|
|
|
/* main.c */
|
|
extern unsigned long x86_stack_size;
|
|
+extern char qemu_proc_pathname[];
|
|
|
|
/* user access */
|
|
|
|
diff --git a/bsd-user/signal.c b/bsd-user/signal.c
|
|
index d56837b..29e8e12 100644
|
|
--- a/bsd-user/signal.c
|
|
+++ b/bsd-user/signal.c
|
|
@@ -77,7 +77,7 @@ static uint8_t host_to_target_signal_table[_NSIG] = {
|
|
[SIGUSR1] = TARGET_SIGUSR1,
|
|
[SIGUSR2] = TARGET_SIGUSR2,
|
|
#ifdef SIGTHR
|
|
- [SIGTHR] = TARGET_SIGTHR,
|
|
+ [SIGTHR + 3] = TARGET_SIGTHR,
|
|
#endif
|
|
/* [SIGLWP] = TARGET_SIGLWP, */
|
|
#ifdef SIGLIBRT
|
|
@@ -207,9 +207,10 @@ target_to_host_sigset(sigset_t *d, const target_sigset_t *s)
|
|
static inline void
|
|
host_to_target_siginfo_noswap(target_siginfo_t *tinfo, const siginfo_t *info)
|
|
{
|
|
- int sig;
|
|
+ int sig, code;
|
|
|
|
sig = host_to_target_signal(info->si_signo);
|
|
+ code = tswap32(info->si_code); /* XXX should have host_to_target_si_code() */
|
|
tinfo->si_signo = sig;
|
|
tinfo->si_errno = info->si_errno;
|
|
tinfo->si_code = info->si_code;
|
|
@@ -222,11 +223,13 @@ host_to_target_siginfo_noswap(target_siginfo_t *tinfo, const siginfo_t *info)
|
|
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) {
|
|
+ if (SIGPOLL == sig) {
|
|
tinfo->_reason._poll._band = info->_reason._poll._band;
|
|
+ }
|
|
#endif
|
|
- } else {
|
|
+ if (SI_TIMER == code) {
|
|
tinfo->_reason._timer._timerid = info->_reason._timer._timerid;
|
|
tinfo->_reason._timer._overrun = info->_reason._timer._overrun;
|
|
}
|
|
@@ -235,8 +238,10 @@ host_to_target_siginfo_noswap(target_siginfo_t *tinfo, const siginfo_t *info)
|
|
static void
|
|
tswap_siginfo(target_siginfo_t *tinfo, const target_siginfo_t *info)
|
|
{
|
|
- int sig;
|
|
+ int sig, code;
|
|
+
|
|
sig = info->si_signo;
|
|
+ code = info->si_code;
|
|
tinfo->si_signo = tswap32(sig);
|
|
tinfo->si_errno = tswap32(info->si_errno);
|
|
tinfo->si_code = tswap32(info->si_code);
|
|
@@ -247,11 +252,13 @@ tswap_siginfo(target_siginfo_t *tinfo, const target_siginfo_t *info)
|
|
SIGBUS == sig || SIGTRAP == sig) {
|
|
tinfo->_reason._fault._trapno =
|
|
tswap32(info->_reason._fault._trapno);
|
|
+ }
|
|
#ifdef SIGPOLL
|
|
- } else if (SIGPOLL == sig) {
|
|
+ if (SIGPOLL == sig) {
|
|
tinfo->_reason._poll._band = tswap32(info->_reason._poll._band);
|
|
+ }
|
|
#endif
|
|
- } else {
|
|
+ if (SI_TIMER == code) {
|
|
tinfo->_reason._timer._timerid =
|
|
tswap32(info->_reason._timer._timerid);
|
|
tinfo->_reason._timer._overrun =
|
|
@@ -286,11 +293,11 @@ core_dump_signal(int sig)
|
|
}
|
|
|
|
/* Signal queue handling. */
|
|
-static inline struct sigqueue *
|
|
+static inline struct qemu_sigqueue *
|
|
alloc_sigqueue(CPUArchState *env)
|
|
{
|
|
TaskState *ts = env->opaque;
|
|
- struct sigqueue *q = ts->first_free;
|
|
+ struct qemu_sigqueue *q = ts->first_free;
|
|
|
|
if (!q)
|
|
return (NULL);
|
|
@@ -299,7 +306,7 @@ alloc_sigqueue(CPUArchState *env)
|
|
}
|
|
|
|
static inline void
|
|
-free_sigqueue(CPUArchState *env, struct sigqueue *q)
|
|
+free_sigqueue(CPUArchState *env, struct qemu_sigqueue *q)
|
|
{
|
|
|
|
TaskState *ts = env->opaque;
|
|
@@ -372,7 +379,7 @@ queue_signal(CPUArchState *env, int sig, target_siginfo_t *info)
|
|
{
|
|
TaskState *ts = env->opaque;
|
|
struct emulated_sigtable *k;
|
|
- struct sigqueue *q, **pq;
|
|
+ struct qemu_sigqueue *q, **pq;
|
|
abi_ulong handler;
|
|
int queue;
|
|
|
|
@@ -606,7 +613,7 @@ do_sigaction(int sig, const struct target_sigaction *act,
|
|
return (ret);
|
|
}
|
|
|
|
-#if defined(TARGET_MIPS) || defined(TARGET_SPARC64)
|
|
+#if defined(TARGET_MIPS64) /* || defined(TARGET_SPARC64) */
|
|
|
|
static inline abi_ulong
|
|
get_sigframe(struct target_sigaction *ka, CPUArchState *regs, size_t frame_size)
|
|
@@ -629,8 +636,8 @@ get_sigframe(struct target_sigaction *ka, CPUArchState *regs, size_t frame_size)
|
|
}
|
|
|
|
/* compare to mips/mips/pm_machdep.c and sparc64/sparc64/machdep.c sendsig() */
|
|
-static void setup_frame(int sig, struct target_sigaction *ka,
|
|
- target_sigset_t *set, CPUArchState *regs)
|
|
+static void setup_frame(int sig, int code, struct target_sigaction *ka,
|
|
+ target_sigset_t *set, target_siginfo_t *tinfo, CPUArchState *regs)
|
|
{
|
|
struct target_sigframe *frame;
|
|
abi_ulong frame_addr;
|
|
@@ -651,6 +658,7 @@ static void setup_frame(int sig, struct target_sigaction *ka,
|
|
if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0))
|
|
goto give_sigsegv;
|
|
|
|
+ memset(frame, 0, sizeof(*frame));
|
|
#if defined(TARGET_MIPS)
|
|
int mflags = on_sig_stack(frame_addr) ? TARGET_MC_ADD_MAGIC :
|
|
TARGET_MC_SET_ONSTACK | TARGET_MC_ADD_MAGIC;
|
|
@@ -666,6 +674,58 @@ static void setup_frame(int sig, struct target_sigaction *ka,
|
|
goto give_sigsegv;
|
|
}
|
|
|
|
+ if (tinfo) {
|
|
+ frame->sf_si.si_signo = tinfo->si_signo;
|
|
+ frame->sf_si.si_errno = tinfo->si_errno;
|
|
+ frame->sf_si.si_code = tinfo->si_code;
|
|
+ frame->sf_si.si_pid = tinfo->si_pid;
|
|
+ frame->sf_si.si_uid = tinfo->si_uid;
|
|
+ frame->sf_si.si_status = tinfo->si_status;
|
|
+ frame->sf_si.si_addr = tinfo->si_addr;
|
|
+
|
|
+ if (TARGET_SIGILL == sig || TARGET_SIGFPE == sig ||
|
|
+ TARGET_SIGSEGV == sig || TARGET_SIGBUS == sig ||
|
|
+ TARGET_SIGTRAP == sig)
|
|
+ frame->sf_si._reason._fault._trapno =
|
|
+ tinfo->_reason._fault._trapno;
|
|
+
|
|
+ /*
|
|
+ * If si_code is one of SI_QUEUE, SI_TIMER, SI_ASYNCIO, or
|
|
+ * SI_MESGQ, then si_value contains the application-specified
|
|
+ * signal value. Otherwise, the contents of si_value are
|
|
+ * undefined.
|
|
+ */
|
|
+ if (SI_QUEUE == code || SI_TIMER == code ||
|
|
+ SI_ASYNCIO == code || SI_MESGQ == code) {
|
|
+ frame->sf_si.si_value.sival_int =
|
|
+ tinfo->si_value.sival_int;
|
|
+ }
|
|
+
|
|
+ if (SI_TIMER == code) {
|
|
+ frame->sf_si._reason._timer._timerid =
|
|
+ tinfo->_reason._timer._timerid;
|
|
+ frame->sf_si._reason._timer._overrun =
|
|
+ tinfo->_reason._timer._overrun;
|
|
+ }
|
|
+
|
|
+#ifdef SIGPOLL
|
|
+ if (SIGPOLL == sig) {
|
|
+ frame->sf_si._reason._band =
|
|
+ tinfo->_reason._band;
|
|
+ }
|
|
+#endif
|
|
+
|
|
+ frame->sf_signum = sig;
|
|
+ frame->sf_siginfo = (abi_ulong)&frame->sf_si;
|
|
+ frame->sf_ucontext = (abi_ulong)&frame->sf_uc;
|
|
+
|
|
+ } else {
|
|
+ frame->sf_signum = sig;
|
|
+ frame->sf_siginfo = 0;
|
|
+ frame->sf_ucontext = 0;
|
|
+ }
|
|
+
|
|
+
|
|
if (set_sigtramp_args(regs, sig, frame, frame_addr, ka))
|
|
goto give_sigsegv;
|
|
|
|
@@ -866,8 +926,8 @@ get_sigframe(struct target_sigaction *ka, CPUSPARCState *regs, size_t 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)
|
|
+static void setup_frame(int sig, int code, struct target_sigaction *ka,
|
|
+ target_sigset_t *set, target_siginfo_t *tinfo, CPUSPARCState *regs)
|
|
{
|
|
struct target_sigframe *frame;
|
|
abi_ulong frame_addr;
|
|
@@ -960,21 +1020,12 @@ badframe:
|
|
#else
|
|
|
|
static void
|
|
-setup_frame(int sig, struct target_sigaction *ka, target_sigset_t *set,
|
|
- CPUArchState *env)
|
|
+setup_frame(int sig, int code, struct target_sigaction *ka, target_sigset_t *set,
|
|
+ target_siginfo_t *tinfo, 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)
|
|
{
|
|
@@ -1043,13 +1094,14 @@ signal_init(void)
|
|
void
|
|
process_pending_signals(CPUArchState *cpu_env)
|
|
{
|
|
- int sig;
|
|
+ int sig, code;
|
|
abi_ulong handler;
|
|
sigset_t set, old_set;
|
|
target_sigset_t target_old_set;
|
|
+ target_siginfo_t tinfo;
|
|
struct emulated_sigtable *k;
|
|
struct target_sigaction *sa;
|
|
- struct sigqueue *q;
|
|
+ struct qemu_sigqueue *q;
|
|
TaskState *ts = cpu_env->opaque;
|
|
|
|
if (!ts->signal_pending)
|
|
@@ -1143,14 +1195,16 @@ handle_signal:
|
|
}
|
|
#endif
|
|
#endif
|
|
+ code = q->info.si_code;
|
|
/* 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,
|
|
+ if (sa->sa_flags & TARGET_SA_SIGINFO) {
|
|
+ tswap_siginfo(&tinfo, &q->info);
|
|
+ setup_frame(sig, code, sa, &target_old_set, &tinfo,
|
|
cpu_env);
|
|
- else
|
|
-#endif
|
|
- setup_frame(sig, sa, &target_old_set, cpu_env);
|
|
+ } else {
|
|
+ setup_frame(sig, code, sa, &target_old_set, NULL,
|
|
+ cpu_env);
|
|
+ }
|
|
if (sa->sa_flags & TARGET_SA_RESETHAND)
|
|
sa->_sa_handler = TARGET_SIG_DFL;
|
|
}
|
|
diff --git a/bsd-user/strace.c b/bsd-user/strace.c
|
|
index d73bbca..7f0f7bd 100644
|
|
--- a/bsd-user/strace.c
|
|
+++ b/bsd-user/strace.c
|
|
@@ -4,7 +4,12 @@
|
|
#include <sys/types.h>
|
|
#include <unistd.h>
|
|
#include <sys/syscall.h>
|
|
+#include <sys/ioccom.h>
|
|
+#include <ctype.h>
|
|
#include "qemu.h"
|
|
+#ifdef __FreeBSD__
|
|
+#include "freebsd/syscall_nr.h"
|
|
+#endif
|
|
|
|
int do_strace=0;
|
|
|
|
@@ -23,6 +28,29 @@ struct syscallname {
|
|
*/
|
|
|
|
static void
|
|
+print_sysctl(const struct syscallname *name,
|
|
+ abi_long arg1, abi_long arg2, abi_long arg3,
|
|
+ abi_long arg4, abi_long arg5, abi_long arg6)
|
|
+{
|
|
+ uint32_t i;
|
|
+ int32_t *namep;
|
|
+
|
|
+
|
|
+ gemu_log("%s({ ", name->name);
|
|
+ namep = lock_user(VERIFY_READ, arg1, sizeof(int32_t) * arg2, 1);
|
|
+ if (namep) {
|
|
+ int32_t *p = namep;
|
|
+
|
|
+ for(i = 0; i < (uint32_t)arg2; i++)
|
|
+ gemu_log("%d ", tswap32(*p++));
|
|
+ unlock_user(namep, arg1, 0);
|
|
+ }
|
|
+ gemu_log("}, %u, 0x" TARGET_ABI_FMT_lx ", 0x" TARGET_ABI_FMT_lx ", 0x"
|
|
+ TARGET_ABI_FMT_lx ", 0x" TARGET_ABI_FMT_lx ")",
|
|
+ (uint32_t)arg2, arg3, arg4, arg5, arg6);
|
|
+}
|
|
+
|
|
+static void
|
|
print_execve(const struct syscallname *name,
|
|
abi_long arg1, abi_long arg2, abi_long arg3,
|
|
abi_long arg4, abi_long arg5, abi_long arg6)
|
|
@@ -30,10 +58,18 @@ print_execve(const struct syscallname *name,
|
|
abi_ulong arg_ptr_addr;
|
|
char *s;
|
|
|
|
- if (!(s = lock_user_string(arg1)))
|
|
- return;
|
|
- gemu_log("%s(\"%s\",{", name->name, s);
|
|
- unlock_user(s, arg1, 0);
|
|
+#ifdef __FreeBSD__
|
|
+ if (TARGET_FREEBSD_NR_fexecve == name->nr) {
|
|
+ gemu_log("%s(%d,{", name->name, (int)arg1);
|
|
+
|
|
+ } else
|
|
+#endif
|
|
+ {
|
|
+ if (!(s = lock_user_string(arg1)))
|
|
+ return;
|
|
+ gemu_log("%s(\"%s\",{", name->name, s);
|
|
+ unlock_user(s, arg1, 0);
|
|
+ }
|
|
|
|
for (arg_ptr_addr = arg2; ; arg_ptr_addr += sizeof(abi_ulong)) {
|
|
abi_ulong *arg_ptr, arg_addr;
|
|
@@ -54,6 +90,54 @@ print_execve(const struct syscallname *name,
|
|
gemu_log("NULL})");
|
|
}
|
|
|
|
+static void
|
|
+print_ioctl(const struct syscallname *name,
|
|
+ abi_long arg1, abi_long arg2, abi_long arg3,
|
|
+ abi_long arg4, abi_long arg5, abi_long arg6)
|
|
+{
|
|
+ /* Decode the ioctl request */
|
|
+ gemu_log("%s(%d, 0x%0lx { IO%s%s GRP:0x%x('%c') CMD:%d LEN:%d }, 0x"
|
|
+ TARGET_ABI_FMT_lx ", ...)",
|
|
+
|
|
+ name->name,
|
|
+ (int)arg1,
|
|
+ (unsigned long)arg2,
|
|
+ arg2 & IOC_OUT ? "R" : "",
|
|
+ arg2 & IOC_IN ? "W" : "",
|
|
+ (unsigned)IOCGROUP(arg2),
|
|
+ isprint(IOCGROUP(arg2)) ? (char)IOCGROUP(arg2) : '?',
|
|
+ (int)arg2 & 0xFF,
|
|
+ (int)IOCPARM_LEN(arg2),
|
|
+ arg3);
|
|
+}
|
|
+
|
|
+static void
|
|
+print_sysarch(const struct syscallname *name,
|
|
+ abi_long arg1, abi_long arg2, abi_long arg3,
|
|
+ abi_long arg4, abi_long arg5, abi_long arg6)
|
|
+{
|
|
+#ifdef TARGET_MIPS
|
|
+ switch(arg1) {
|
|
+ case 1:
|
|
+ gemu_log("%s(SET_TLS, 0x" TARGET_ABI_FMT_lx ")",
|
|
+ name->name, arg2);
|
|
+ break;
|
|
+
|
|
+ case 2:
|
|
+ gemu_log("%s(GET_TLS, 0x" TARGET_ABI_FMT_lx ")",
|
|
+ name->name, arg2);
|
|
+ break;
|
|
+
|
|
+ default:
|
|
+ gemu_log("UNKNOWN OP: %d, " TARGET_ABI_FMT_lx ")",
|
|
+ (int)arg1, arg2);
|
|
+ }
|
|
+#else
|
|
+ gemu_log("%s(%d, " TARGET_ABI_FMT_lx ", " TARGET_ABI_FMT_lx ", "
|
|
+ TARGET_ABI_FMT_lx ")", name->name, (int)arg1, arg2, arg3, arg4);
|
|
+#endif
|
|
+}
|
|
+
|
|
/*
|
|
* Variants for the return value output function
|
|
*/
|
|
diff --git a/bsd-user/syscall.c b/bsd-user/syscall.c
|
|
index 8565ae8..74b5c86 100644
|
|
--- a/bsd-user/syscall.c
|
|
+++ b/bsd-user/syscall.c
|
|
@@ -2,7 +2,7 @@
|
|
* BSD syscalls
|
|
*
|
|
* Copyright (c) 2003 - 2008 Fabrice Bellard
|
|
- * Copyright (c) 2012 Stacey Son <sson@FreeBSD.org>
|
|
+ * Copyright (c) 2012 - 2013 Stacey Son <sson@FreeBSD.org>
|
|
*
|
|
* This program is free software; you can redistribute it and/or modify
|
|
* it under the terms of the GNU General Public License as published by
|
|
@@ -33,6 +33,7 @@
|
|
#include <stdio.h>
|
|
#include <stdint.h>
|
|
#include <stdarg.h>
|
|
+#include <stddef.h>
|
|
#include <string.h>
|
|
#include <dirent.h>
|
|
#include <errno.h>
|
|
@@ -68,8 +69,12 @@
|
|
#include <sys/termios.h>
|
|
#endif
|
|
#include <sys/ttycom.h>
|
|
+#include <sys/filio.h>
|
|
#include <sys/reboot.h>
|
|
#include <sys/timex.h>
|
|
+#define _ACL_PRIVATE
|
|
+#include <sys/acl.h>
|
|
+#include <sys/extattr.h>
|
|
#include <kenv.h>
|
|
#include <pthread.h>
|
|
#include <machine/atomic.h>
|
|
@@ -87,6 +92,7 @@
|
|
#include "qemu-common.h"
|
|
#ifdef __FreeBSD__
|
|
#include "freebsd/ttycom.h"
|
|
+#include "freebsd/filio.h"
|
|
#endif
|
|
|
|
|
|
@@ -95,6 +101,70 @@
|
|
static abi_ulong target_brk;
|
|
static abi_ulong target_original_brk;
|
|
|
|
+static char *get_filename_from_fd(pid_t pid, int fd, char *filename, size_t len);
|
|
+
|
|
+#ifdef __FreeBSD__
|
|
+#include <sys/queue.h>
|
|
+#include <sys/user.h>
|
|
+#include <libprocstat.h>
|
|
+
|
|
+
|
|
+/*
|
|
+ * Get the filename for the given file descriptor.
|
|
+ * Note that this may return NULL (fail) if no longer cached in the kernel.
|
|
+ */
|
|
+static char *
|
|
+get_filename_from_fd(pid_t pid, int fd, char *filename, size_t len)
|
|
+{
|
|
+ unsigned int cnt;
|
|
+ struct procstat *procstat = NULL;
|
|
+ struct kinfo_proc *kipp = NULL;
|
|
+ struct filestat_list *head = NULL;
|
|
+ struct filestat *fst;
|
|
+ char *ret = NULL;
|
|
+
|
|
+ procstat = procstat_open_sysctl();
|
|
+ if (NULL == procstat)
|
|
+ goto out;
|
|
+
|
|
+ kipp = procstat_getprocs(procstat, KERN_PROC_PID, pid, &cnt);
|
|
+ if (NULL == kipp)
|
|
+ goto out;
|
|
+
|
|
+ head = procstat_getfiles(procstat, kipp, 0);
|
|
+ if (NULL == head)
|
|
+ goto out;
|
|
+
|
|
+ STAILQ_FOREACH(fst, head, next) {
|
|
+ if (fd == fst->fs_fd) {
|
|
+ if (fst->fs_path != NULL) {
|
|
+ (void)strlcpy(filename, fst->fs_path, len);
|
|
+ ret = filename;
|
|
+ }
|
|
+ break;
|
|
+ }
|
|
+ }
|
|
+
|
|
+out:
|
|
+ if (head != NULL)
|
|
+ procstat_freefiles(procstat, head);
|
|
+ if (kipp != NULL)
|
|
+ procstat_freeprocs(procstat, kipp);
|
|
+ if (procstat != NULL)
|
|
+ procstat_close(procstat);
|
|
+ return (ret);
|
|
+}
|
|
+
|
|
+#else
|
|
+
|
|
+static char *
|
|
+get_filename_from_fd(pid_t pid, int fd, char *filename, size_t len)
|
|
+{
|
|
+ return (NULL);
|
|
+}
|
|
+
|
|
+#endif /* ! __FreeBSD__ */
|
|
+
|
|
static inline abi_long get_errno(abi_long ret)
|
|
{
|
|
if (ret == -1)
|
|
@@ -297,9 +367,9 @@ static abi_long do_freebsd_sysarch(void *env, int op, abi_ulong parms)
|
|
|
|
switch(op) {
|
|
case TARGET_MIPS_SET_TLS:
|
|
- if (get_user(mips_env->tls_value, parms, abi_ulong))
|
|
- ret = -TARGET_EFAULT;
|
|
+ mips_env->tls_value = parms;
|
|
break;
|
|
+
|
|
case TARGET_MIPS_GET_TLS:
|
|
if (put_user(mips_env->tls_value, parms, abi_ulong))
|
|
ret = -TARGET_EFAULT;
|
|
@@ -386,24 +456,46 @@ static int sysctl_oldcvt(void *holdp, size_t holdlen, uint32_t kind)
|
|
return 0;
|
|
}
|
|
|
|
+/*
|
|
+ * Convert the undocmented name2oid sysctl data for the target.
|
|
+ */
|
|
+static inline void
|
|
+sysctl_name2oid(uint32_t *holdp, size_t holdlen)
|
|
+{
|
|
+ size_t i;
|
|
+
|
|
+ for(i = 0; i < holdlen; i++)
|
|
+ holdp[i] = tswap32(holdp[i]);
|
|
+}
|
|
+
|
|
+static inline void
|
|
+sysctl_oidfmt(uint32_t *holdp)
|
|
+{
|
|
+ /* byte swap the kind */
|
|
+ holdp[0] = tswap32(holdp[0]);
|
|
+}
|
|
+
|
|
/* XXX this needs to be emulated on non-FreeBSD hosts... */
|
|
static abi_long do_freebsd_sysctl(abi_ulong namep, int32_t namelen, abi_ulong oldp,
|
|
abi_ulong oldlenp, abi_ulong newp, abi_ulong newlen)
|
|
{
|
|
abi_long ret;
|
|
- void *hnamep, *holdp, *hnewp = NULL;
|
|
+ void *hnamep, *holdp = NULL, *hnewp = NULL;
|
|
size_t holdlen;
|
|
abi_ulong oldlen = 0;
|
|
int32_t *snamep = g_malloc(sizeof(int32_t) * namelen), *p, *q, i;
|
|
uint32_t kind = 0;
|
|
+ abi_ulong argv, argv0;
|
|
+ char *fullpath = NULL;
|
|
|
|
if (oldlenp)
|
|
- get_user_ual(oldlen, oldlenp);
|
|
+ if (get_user_ual(oldlen, oldlenp))
|
|
+ return -TARGET_EFAULT;
|
|
if (!(hnamep = lock_user(VERIFY_READ, namep, namelen, 1)))
|
|
return -TARGET_EFAULT;
|
|
if (newp && !(hnewp = lock_user(VERIFY_READ, newp, newlen, 1)))
|
|
return -TARGET_EFAULT;
|
|
- if (!(holdp = lock_user(VERIFY_WRITE, oldp, oldlen, 0)))
|
|
+ if (oldp && !(holdp = lock_user(VERIFY_WRITE, oldp, oldlen, 0)))
|
|
return -TARGET_EFAULT;
|
|
holdlen = oldlen;
|
|
for (p = hnamep, q = snamep, i = 0; i < namelen; p++, i++)
|
|
@@ -411,7 +503,8 @@ static abi_long do_freebsd_sysctl(abi_ulong namep, int32_t namelen, abi_ulong ol
|
|
oidfmt(snamep, namelen, NULL, &kind);
|
|
|
|
/* Handle some arch/emulator dependent sysctl()'s here. */
|
|
- if (CTL_KERN == snamep[0]) {
|
|
+ switch(snamep[0]) {
|
|
+ case CTL_KERN:
|
|
switch(snamep[1]) {
|
|
case KERN_USRSTACK:
|
|
#if defined(TARGET_ARM) && HOST_LONG_BITS == 64 && TARGET_ABI_BITS == 32
|
|
@@ -437,17 +530,77 @@ static abi_long do_freebsd_sysctl(abi_ulong namep, int32_t namelen, abi_ulong ol
|
|
#endif
|
|
goto out;
|
|
|
|
+ case KERN_PROC:
|
|
+ switch(snamep[2]) {
|
|
+ case KERN_PROC_PATHNAME:
|
|
+ if (get_user_ual(argv, TARGET_PS_STRINGS)) {
|
|
+ ret = -TARGET_EFAULT;
|
|
+ goto out;
|
|
+ }
|
|
+ if (get_user_ual(argv0, argv)) {
|
|
+ ret = -TARGET_EFAULT;
|
|
+ goto out;
|
|
+ }
|
|
+
|
|
+ fullpath = realpath(g2h(argv0), NULL);
|
|
+ if (NULL == fullpath)
|
|
+ fullpath = (char *)g2h(argv0);
|
|
+ holdlen = strlen(fullpath) + 1;
|
|
+ if (holdp) {
|
|
+ if (oldlen < holdlen) {
|
|
+ ret = -TARGET_EINVAL;
|
|
+ goto out;
|
|
+ }
|
|
+ if (!access_ok(VERIFY_WRITE, argv0,
|
|
+ holdlen)) {
|
|
+ ret = -TARGET_EFAULT;
|
|
+ goto out;
|
|
+ }
|
|
+ strlcpy(holdp, fullpath, oldlen);
|
|
+ }
|
|
+ ret = 0;
|
|
+ goto out;
|
|
+
|
|
+ default:
|
|
+ break;
|
|
+ }
|
|
+ break;
|
|
+
|
|
default:
|
|
break;
|
|
}
|
|
+ break;
|
|
+
|
|
+ default:
|
|
+ break;
|
|
}
|
|
|
|
ret = get_errno(sysctl(snamep, namelen, holdp, &holdlen, hnewp, newlen));
|
|
- if (!ret)
|
|
- sysctl_oldcvt(holdp, holdlen, kind);
|
|
+ if (!ret && (holdp != 0 && holdlen != 0)) {
|
|
+ if (0 == snamep[0] && (3 == snamep[1] || 4 == snamep[1])) {
|
|
+ if (3 == snamep[1]) {
|
|
+ /* Handle the undocumented name2oid special case. */
|
|
+ sysctl_name2oid(holdp, holdlen);
|
|
+ } else {
|
|
+ /* Handle oidfmt */
|
|
+ sysctl_oidfmt(holdp);
|
|
+ }
|
|
+ } else {
|
|
+ sysctl_oldcvt(holdp, holdlen, kind);
|
|
+ }
|
|
+ }
|
|
+#ifdef DEBUG
|
|
+ else {
|
|
+ printf("sysctl(mib[0]=%d, mib[1]=%d, mib[3]=%d...) returned %d\n",
|
|
+ snamep[0], snamep[1], snamep[2], (int)ret);
|
|
+ }
|
|
+#endif
|
|
|
|
out:
|
|
- put_user_ual(holdlen, oldlenp);
|
|
+ if (fullpath)
|
|
+ free(fullpath);
|
|
+ if (oldlenp)
|
|
+ put_user_ual(holdlen, oldlenp);
|
|
unlock_user(hnamep, namep, 0);
|
|
unlock_user(holdp, oldp, holdlen);
|
|
if (hnewp)
|
|
@@ -509,6 +662,24 @@ static abi_long unlock_iovec(struct iovec *vec, abi_ulong target_addr,
|
|
}
|
|
|
|
static inline abi_long
|
|
+target_to_host_ip_mreq(struct ip_mreqn *mreqn, abi_ulong target_addr,
|
|
+ socklen_t len)
|
|
+{
|
|
+ struct target_ip_mreqn *target_smreqn;
|
|
+
|
|
+ target_smreqn = lock_user(VERIFY_READ, target_addr, len, 1);
|
|
+ if (!target_smreqn)
|
|
+ return -TARGET_EFAULT;
|
|
+ mreqn->imr_multiaddr.s_addr = target_smreqn->imr_multiaddr.s_addr;
|
|
+ mreqn->imr_address.s_addr = target_smreqn->imr_address.s_addr;
|
|
+ if (len == sizeof(struct target_ip_mreqn))
|
|
+ mreqn->imr_ifindex = tswapal(target_smreqn->imr_ifindex);
|
|
+ unlock_user(target_smreqn, target_addr, 0);
|
|
+
|
|
+ return (0);
|
|
+}
|
|
+
|
|
+static inline abi_long
|
|
target_to_host_sockaddr(struct sockaddr *addr, abi_ulong target_addr,
|
|
socklen_t len)
|
|
{
|
|
@@ -1554,11 +1725,62 @@ int_case:
|
|
}
|
|
break;
|
|
|
|
+ case IPPROTO_TCP:
|
|
+ /* TCP options all take an 'int' value. */
|
|
+ goto int_case;
|
|
+
|
|
+ case IPPROTO_IP:
|
|
+ switch(optname) {
|
|
+ case IP_HDRINCL:
|
|
+ case IP_TOS:
|
|
+ case IP_TTL:
|
|
+ case IP_RECVOPTS:
|
|
+ case IP_RECVRETOPTS:
|
|
+ case IP_RECVDSTADDR:
|
|
+
|
|
+ case IP_RETOPTS:
|
|
+ case IP_RECVTOS:
|
|
+ case IP_MULTICAST_TTL:
|
|
+ case IP_MULTICAST_LOOP:
|
|
+ case IP_PORTRANGE:
|
|
+ case IP_IPSEC_POLICY:
|
|
+ case IP_FAITH:
|
|
+ case IP_ONESBCAST:
|
|
+ case IP_BINDANY:
|
|
+ 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 < sizeof(int) && len > 0 && val >= 0 &&
|
|
+ val < 255) {
|
|
+ len = 1;
|
|
+ if (put_user_u32(len, optlen)
|
|
+ || put_user_u8(val, optval_addr))
|
|
+ return (-TARGET_EFAULT);
|
|
+ } else {
|
|
+ if (len > sizeof(int))
|
|
+ len = sizeof(int);
|
|
+ if (put_user_u32(len, optlen)
|
|
+ || put_user_u32(val, optval_addr))
|
|
+ return (-TARGET_EFAULT);
|
|
+ }
|
|
+ break;
|
|
+
|
|
+ default:
|
|
+ goto unimplemented;
|
|
+ }
|
|
+ break;
|
|
+
|
|
default:
|
|
unimplemented:
|
|
gemu_log("getsockopt level=%d optname=%d not yet supported\n",
|
|
level, optname);
|
|
- ret = -TARGET_EOPNOTSUPP;
|
|
+ ret = (-TARGET_EOPNOTSUPP);
|
|
break;
|
|
}
|
|
return (ret);
|
|
@@ -1569,10 +1791,67 @@ static abi_long
|
|
do_setsockopt(int sockfd, int level, int optname, abi_ulong optval_addr,
|
|
socklen_t optlen)
|
|
{
|
|
- int val;
|
|
abi_long ret;
|
|
+ int val;
|
|
+ struct ip_mreqn *ip_mreq;
|
|
|
|
switch(level) {
|
|
+ case IPPROTO_TCP:
|
|
+ /* TCP options all take an 'int' value. */
|
|
+ if (optlen < sizeof(uint32_t))
|
|
+ return (-TARGET_EINVAL);
|
|
+
|
|
+ if (get_user_u32(val, optval_addr))
|
|
+ return (-TARGET_EFAULT);
|
|
+ ret = get_errno(setsockopt(sockfd, level, optname, &val,
|
|
+ sizeof(val)));
|
|
+ break;
|
|
+
|
|
+ case IPPROTO_IP:
|
|
+ switch (optname) {
|
|
+ case IP_HDRINCL:/* int; header is included with data */
|
|
+ case IP_TOS: /* int; IP type of service and preced. */
|
|
+ case IP_TTL: /* int; IP time to live */
|
|
+ case IP_RECVOPTS: /* bool; receive all IP opts w/dgram */
|
|
+ case IP_RECVRETOPTS: /* bool; receive IP opts for response */
|
|
+ case IP_RECVDSTADDR: /* bool; receive IP dst addr w/dgram */
|
|
+ case IP_MULTICAST_IF:/* u_char; set/get IP multicast i/f */
|
|
+ case IP_MULTICAST_TTL:/* u_char; set/get IP multicast ttl */
|
|
+ case IP_MULTICAST_LOOP:/*u_char;set/get IP multicast loopback */
|
|
+ case IP_PORTRANGE: /* int; range to choose for unspec port */
|
|
+ case IP_RECVIF: /* bool; receive reception if w/dgram */
|
|
+ case IP_IPSEC_POLICY: /* int; set/get security policy */
|
|
+ case IP_FAITH: /* bool; accept FAITH'ed connections */
|
|
+ case IP_RECVTTL: /* bool; receive reception TTL w/dgram */
|
|
+ val = 0;
|
|
+ if (optlen >= sizeof(uint32_t)) {
|
|
+ if (get_user_u32(val, optval_addr))
|
|
+ return (-TARGET_EFAULT);
|
|
+ } else if (optlen >= 1) {
|
|
+ if (get_user_u8(val, optval_addr))
|
|
+ return (-TARGET_EFAULT);
|
|
+ }
|
|
+ ret = get_errno(setsockopt(sockfd, level, optname,
|
|
+ &val, sizeof(val)));
|
|
+ break;
|
|
+
|
|
+ case IP_ADD_MEMBERSHIP: /*ip_mreq; add an IP group membership */
|
|
+ case IP_DROP_MEMBERSHIP:/*ip_mreq; drop an IP group membership*/
|
|
+ if (optlen < sizeof (struct target_ip_mreq) ||
|
|
+ optlen > sizeof (struct target_ip_mreqn))
|
|
+ return (-TARGET_EINVAL);
|
|
+ ip_mreq = (struct ip_mreqn *) alloca(optlen);
|
|
+ target_to_host_ip_mreq(ip_mreq, optval_addr, optlen);
|
|
+ ret = get_errno(setsockopt(sockfd, level, optname,
|
|
+ ip_mreq, optlen));
|
|
+ break;
|
|
+
|
|
+ default:
|
|
+ goto unimplemented;
|
|
+ }
|
|
+ break;
|
|
+
|
|
+
|
|
case TARGET_SOL_SOCKET:
|
|
switch (optname) {
|
|
/* Options with 'int' argument. */
|
|
@@ -1730,13 +2009,15 @@ target_to_host_semarray(int semid, unsigned short **host_array,
|
|
if (ret == -1)
|
|
return (get_errno(ret));
|
|
nsems = semid_ds.sem_nsems;
|
|
- *host_array = malloc(nsems * sizeof(unsigned short));
|
|
+ *host_array = (unsigned short *)malloc(nsems * sizeof(unsigned short));
|
|
array = lock_user(VERIFY_READ, target_addr,
|
|
nsems*sizeof(unsigned short), 1);
|
|
- if (!array)
|
|
+ if (!array) {
|
|
+ free(*host_array);
|
|
return (-TARGET_EFAULT);
|
|
+ }
|
|
for(i=0; i<nsems; i++) {
|
|
- __get_user((*host_array)[i], &array[i]);
|
|
+ (*host_array)[i] = array[i];
|
|
}
|
|
unlock_user(array, target_addr, 0);
|
|
|
|
@@ -1756,18 +2037,21 @@ host_to_target_semarray(int semid, abi_ulong target_addr,
|
|
semun.buf = &semid_ds;
|
|
|
|
ret = semctl(semid, 0, IPC_STAT, semun);
|
|
- if (ret == -1)
|
|
+ if (ret == -1) {
|
|
+ free(*host_array);
|
|
return get_errno(ret);
|
|
+ }
|
|
|
|
nsems = semid_ds.sem_nsems;
|
|
-
|
|
- array = lock_user(VERIFY_WRITE, target_addr,
|
|
+ array = (unsigned short *)lock_user(VERIFY_WRITE, target_addr,
|
|
nsems*sizeof(unsigned short), 0);
|
|
- if (!array)
|
|
+ if (!array) {
|
|
+ free(*host_array);
|
|
return (-TARGET_EFAULT);
|
|
+ }
|
|
|
|
for(i=0; i<nsems; i++) {
|
|
- __put_user((*host_array)[i], &array[i]);
|
|
+ array[i] = (*host_array)[i];
|
|
}
|
|
free(*host_array);
|
|
unlock_user(array, target_addr, 1);
|
|
@@ -1779,19 +2063,17 @@ static inline abi_long
|
|
target_to_host_ipc_perm(struct ipc_perm *host_ip, abi_ulong target_addr)
|
|
{
|
|
struct target_ipc_perm *target_ip;
|
|
- struct target_semid_ds *target_sd;
|
|
|
|
- if (!lock_user_struct(VERIFY_READ, target_sd, target_addr, 1))
|
|
+ if (!lock_user_struct(VERIFY_READ, target_ip, target_addr, 1))
|
|
return (-TARGET_EFAULT);
|
|
- target_ip = &(target_sd->sem_perm);
|
|
- host_ip->cuid = tswapal(target_ip->cuid);
|
|
- host_ip->cgid = tswapal(target_ip->cgid);
|
|
- host_ip->uid = tswapal(target_ip->uid);
|
|
- host_ip->gid = tswapal(target_ip->gid);
|
|
+ host_ip->cuid = tswap32(target_ip->cuid);
|
|
+ host_ip->cgid = tswap32(target_ip->cgid);
|
|
+ host_ip->uid = tswap32(target_ip->uid);
|
|
+ host_ip->gid = tswap32(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);
|
|
+ unlock_user_struct(target_ip, target_addr, 0);
|
|
|
|
return (0);
|
|
}
|
|
@@ -1800,18 +2082,17 @@ 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))
|
|
+
|
|
+ if (!lock_user_struct(VERIFY_WRITE, target_ip, 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->cuid = tswap32(host_ip->cuid);
|
|
+ target_ip->cgid = tswap32(host_ip->cgid);
|
|
+ target_ip->uid = tswap32(host_ip->uid);
|
|
+ target_ip->gid = tswap32(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);
|
|
+ unlock_user_struct(target_ip, target_addr, 1);
|
|
return (0);
|
|
}
|
|
|
|
@@ -1822,11 +2103,12 @@ target_to_host_semid_ds(struct semid_ds *host_sd, abi_ulong target_addr)
|
|
|
|
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))
|
|
+ if (target_to_host_ipc_perm(&(host_sd->sem_perm), (target_addr +
|
|
+ offsetof(struct target_semid_ds, sem_perm)) ))
|
|
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_base = g2h(target_sd->sem_base); */
|
|
+ host_sd->sem_nsems = tswap16(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);
|
|
@@ -1840,10 +2122,13 @@ host_to_target_semid_ds(abi_ulong target_addr, struct semid_ds *host_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)))
|
|
+ if (host_to_target_ipc_perm((target_addr +
|
|
+ offsetof(struct target_semid_ds, sem_perm)),
|
|
+ &(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_base = h2g((void *)host_sd->sem_base); */
|
|
+ target_sd->sem_nsems = tswap16(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);
|
|
@@ -1859,6 +2144,7 @@ do_semctl(int semid, int semnum, int cmd, union target_semun target_su)
|
|
unsigned short *array = NULL;
|
|
abi_long ret = -TARGET_EINVAL;
|
|
abi_long err;
|
|
+ abi_ulong target_addr;
|
|
|
|
cmd &= 0xff;
|
|
|
|
@@ -1872,24 +2158,28 @@ do_semctl(int semid, int semnum, int cmd, union target_semun target_su)
|
|
|
|
case GETALL:
|
|
case SETALL:
|
|
- err = target_to_host_semarray(semid, &array, target_su.array);
|
|
+ if (get_user_ual(target_addr, (abi_ulong)target_su.array))
|
|
+ return (-TARGET_EFAULT);
|
|
+ err = target_to_host_semarray(semid, &array, target_addr);
|
|
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);
|
|
+ err = host_to_target_semarray(semid, target_addr, &array);
|
|
if (err)
|
|
return (err);
|
|
break;
|
|
|
|
case IPC_STAT:
|
|
case IPC_SET:
|
|
- err = target_to_host_semid_ds(&dsarg, target_su.buf);
|
|
+ if (get_user_ual(target_addr, (abi_ulong)target_su.buf))
|
|
+ return (-TARGET_EFAULT);
|
|
+ err = target_to_host_semid_ds(&dsarg, target_addr);
|
|
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);
|
|
+ err = host_to_target_semid_ds(target_addr, &dsarg);
|
|
if (err)
|
|
return (err);
|
|
break;
|
|
@@ -3383,6 +3673,64 @@ host_to_target_sched_param(abi_ulong target_addr, struct sched_param *host_sp)
|
|
}
|
|
|
|
static inline abi_long
|
|
+target_to_host_acl(struct acl *host_acl, abi_ulong target_addr)
|
|
+{
|
|
+ uint32_t i;
|
|
+ struct target_acl *target_acl;
|
|
+
|
|
+ if (!lock_user_struct(VERIFY_READ, target_acl, target_addr, 1))
|
|
+ return (-TARGET_EFAULT);
|
|
+
|
|
+ __get_user(host_acl->acl_maxcnt, &target_acl->acl_maxcnt);
|
|
+ __get_user(host_acl->acl_cnt, &target_acl->acl_cnt);
|
|
+
|
|
+ for(i = 0; i < host_acl->acl_maxcnt; i++) {
|
|
+ __get_user(host_acl->acl_entry[i].ae_tag,
|
|
+ &target_acl->acl_entry[i].ae_tag);
|
|
+ __get_user(host_acl->acl_entry[i].ae_id,
|
|
+ &target_acl->acl_entry[i].ae_id);
|
|
+ __get_user(host_acl->acl_entry[i].ae_perm,
|
|
+ &target_acl->acl_entry[i].ae_perm);
|
|
+ __get_user(host_acl->acl_entry[i].ae_entry_type,
|
|
+ &target_acl->acl_entry[i].ae_entry_type);
|
|
+ __get_user(host_acl->acl_entry[i].ae_flags,
|
|
+ &target_acl->acl_entry[i].ae_flags);
|
|
+ }
|
|
+
|
|
+ unlock_user_struct(target_acl, target_addr, 0);
|
|
+ return (0);
|
|
+}
|
|
+
|
|
+static inline abi_long
|
|
+host_to_target_acl(abi_ulong target_addr, struct acl *host_acl)
|
|
+{
|
|
+ uint32_t i;
|
|
+ struct target_acl *target_acl;
|
|
+
|
|
+ if (!lock_user_struct(VERIFY_WRITE, target_acl, target_addr, 0))
|
|
+ return (-TARGET_EFAULT);
|
|
+
|
|
+ __put_user(host_acl->acl_maxcnt, &target_acl->acl_maxcnt);
|
|
+ __put_user(host_acl->acl_cnt, &target_acl->acl_cnt);
|
|
+
|
|
+ for(i = 0; i < host_acl->acl_maxcnt; i++) {
|
|
+ __put_user(host_acl->acl_entry[i].ae_tag,
|
|
+ &target_acl->acl_entry[i].ae_tag);
|
|
+ __put_user(host_acl->acl_entry[i].ae_id,
|
|
+ &target_acl->acl_entry[i].ae_id);
|
|
+ __put_user(host_acl->acl_entry[i].ae_perm,
|
|
+ &target_acl->acl_entry[i].ae_perm);
|
|
+ __get_user(host_acl->acl_entry[i].ae_entry_type,
|
|
+ &target_acl->acl_entry[i].ae_entry_type);
|
|
+ __get_user(host_acl->acl_entry[i].ae_flags,
|
|
+ &target_acl->acl_entry[i].ae_flags);
|
|
+ }
|
|
+
|
|
+ unlock_user_struct(target_acl, target_addr, 1);
|
|
+ return (0);
|
|
+}
|
|
+
|
|
+static inline abi_long
|
|
do_sched_setparam(pid_t pid, abi_ulong target_sp_addr)
|
|
{
|
|
int ret;
|
|
@@ -3993,10 +4341,10 @@ static IOCTLEntry ioctl_entries[] = {
|
|
{ TARGET_ ## cmd, cmd, #cmd, access, 0, { __VA_ARGS__ } },
|
|
#define IOCTL_SPECIAL(cmd, access, dofn, ...) \
|
|
{ TARGET_ ## cmd, cmd, #cmd, access, dofn, { __VA_ARGS__ } },
|
|
-#ifdef __FreeBSD__
|
|
-#include "freebsd/ioctl.h"
|
|
+#if defined(__FreeBSD__)
|
|
+#include "freebsd/ioctls.h"
|
|
#else
|
|
-#warning No ioctl.h
|
|
+#warning No *bsd/ioctls.h
|
|
#endif
|
|
{ 0, 0 },
|
|
};
|
|
@@ -4096,6 +4444,158 @@ do_ioctl(int fd, abi_long cmd, abi_long arg)
|
|
return (ret);
|
|
}
|
|
|
|
+static inline abi_long
|
|
+freebsd_exec_common(abi_ulong path_or_fd, abi_ulong guest_argp,
|
|
+ abi_ulong guest_envp, int do_fexec)
|
|
+{
|
|
+ char **argp, **envp, **qargp, **qarg1;
|
|
+ int argc, envc;
|
|
+ abi_ulong gp;
|
|
+ abi_ulong addr;
|
|
+ char **q;
|
|
+ int total_size = 0;
|
|
+ void *p;
|
|
+ abi_long ret;
|
|
+
|
|
+ argc = 0;
|
|
+ for (gp = guest_argp; gp; gp += sizeof(abi_ulong)) {
|
|
+ if (get_user_ual(addr, gp))
|
|
+ return (-TARGET_EFAULT);
|
|
+ if (!addr)
|
|
+ break;
|
|
+ argc++;
|
|
+ }
|
|
+ envc = 0;
|
|
+ for (gp = guest_envp; gp; gp += sizeof(abi_ulong)) {
|
|
+ if (get_user_ual(addr, gp))
|
|
+ return (-TARGET_EFAULT);
|
|
+ if (!addr)
|
|
+ break;
|
|
+ envc++;
|
|
+ }
|
|
+
|
|
+ qargp = argp = alloca((argc + 3) * sizeof(void *));
|
|
+ /* save the first agrument for the emulator */
|
|
+ *argp++ = (char *)getprogname();
|
|
+ qarg1 = argp;
|
|
+ envp = alloca((envc + 1) * sizeof(void *));
|
|
+ for (gp = guest_argp, q = argp; gp; gp += sizeof(abi_ulong), q++) {
|
|
+ if (get_user_ual(addr, gp)) {
|
|
+ ret = -TARGET_EFAULT;
|
|
+ goto execve_end;
|
|
+ }
|
|
+ if (!addr)
|
|
+ break;
|
|
+ if (!(*q = lock_user_string(addr))) {
|
|
+ ret = -TARGET_EFAULT;
|
|
+ goto execve_end;
|
|
+ }
|
|
+ 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)) {
|
|
+ ret = -TARGET_EFAULT;
|
|
+ goto execve_end;
|
|
+ }
|
|
+ if (!addr)
|
|
+ break;
|
|
+ if (!(*q = lock_user_string(addr))) {
|
|
+ ret = -TARGET_EFAULT;
|
|
+ goto execve_end;
|
|
+ }
|
|
+ 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 (do_fexec) {
|
|
+ if (((int)path_or_fd > 0 &&
|
|
+ is_target_elf_binary((int)path_or_fd)) == 1) {
|
|
+ char execpath[PATH_MAX];
|
|
+
|
|
+ /*
|
|
+ * The executable is an elf binary for the target
|
|
+ * arch. execve() it using the emulator if we can
|
|
+ * determine the filename path from the fd.
|
|
+ */
|
|
+ if (get_filename_from_fd(getpid(), (int)path_or_fd,
|
|
+ execpath, sizeof(execpath)) != NULL) {
|
|
+ *qarg1 = execpath;
|
|
+ ret = get_errno(execve(qemu_proc_pathname,
|
|
+ qargp, envp));
|
|
+ } else {
|
|
+ /* Getting the filename path failed. */
|
|
+ ret = -TARGET_EBADF;
|
|
+ goto execve_end;
|
|
+ }
|
|
+ } else {
|
|
+ ret = get_errno(fexecve((int)path_or_fd, argp, envp));
|
|
+ }
|
|
+ } else {
|
|
+ int fd;
|
|
+
|
|
+ if (!(p = lock_user_string(path_or_fd))) {
|
|
+ ret = -TARGET_EFAULT;
|
|
+ goto execve_end;
|
|
+ }
|
|
+
|
|
+ /*
|
|
+ * Check the header and see if it a target elf binary. If so
|
|
+ * then execute using qemu user mode emulator.
|
|
+ */
|
|
+ fd = open(p, O_RDONLY | O_CLOEXEC);
|
|
+ if (fd > 0 && is_target_elf_binary(fd) == 1) {
|
|
+ close(fd);
|
|
+ /* Execve() as a target binary using emulator. */
|
|
+ *qarg1 = (char *)p;
|
|
+ ret = get_errno(execve(qemu_proc_pathname, qargp, envp));
|
|
+ } else {
|
|
+ close(fd);
|
|
+ /* Execve() as a host native binary. */
|
|
+ ret = get_errno(execve(p, argp, envp));
|
|
+ }
|
|
+ unlock_user(p, path_or_fd, 0);
|
|
+ }
|
|
+
|
|
+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);
|
|
+ }
|
|
+ return (ret);
|
|
+}
|
|
+
|
|
+static inline abi_long
|
|
+do_freebsd_execve(abi_ulong path_or_fd, abi_ulong argp, abi_ulong envp)
|
|
+{
|
|
+
|
|
+ return (freebsd_exec_common(path_or_fd, argp, envp, 0));
|
|
+}
|
|
+
|
|
+static inline abi_long
|
|
+do_freebsd_fexecve(abi_ulong path_or_fd, abi_ulong argp, abi_ulong envp)
|
|
+{
|
|
+
|
|
+ return (freebsd_exec_common(path_or_fd, argp, envp, 1));
|
|
+}
|
|
+
|
|
/* do_syscall() should always have a single exit point at the end so
|
|
that actions, such as logging of syscall results, can be performed.
|
|
All errnos that do_syscall() returns must be -TARGET_<errcode>. */
|
|
@@ -4515,96 +5015,14 @@ abi_long do_freebsd_syscall(void *cpu_env, int num, abi_long arg1,
|
|
#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;
|
|
+ ret = do_freebsd_execve(arg1, arg2, arg3);
|
|
+ break;
|
|
|
|
- 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);
|
|
- }
|
|
- }
|
|
+ case TARGET_FREEBSD_NR_fexecve:
|
|
+ ret = do_freebsd_fexecve(arg1, arg2, arg3);
|
|
break;
|
|
|
|
+
|
|
case TARGET_FREEBSD_NR_pipe:
|
|
{
|
|
int host_pipe[2];
|
|
@@ -5296,11 +5714,11 @@ abi_long do_freebsd_syscall(void *cpu_env, int num, abi_long arg1,
|
|
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_type = tswap16(target_fl->l_type);
|
|
+ fl.l_whence = tswap16(target_fl->l_whence);
|
|
fl.l_sysid = tswap32(target_fl->l_sysid);
|
|
unlock_user_struct(target_fl, arg3, 0);
|
|
ret = get_errno(fcntl(arg1, host_cmd, &fl));
|
|
@@ -5370,13 +5788,16 @@ abi_long do_freebsd_syscall(void *cpu_env, int num, abi_long arg1,
|
|
if (reclen > len)
|
|
break;
|
|
de->d_reclen = tswap16(reclen);
|
|
+ de->d_fileno = tswap32(de->d_fileno);
|
|
len -= reclen;
|
|
+ de = (struct dirent *)((void *)de + reclen);
|
|
}
|
|
}
|
|
unlock_user(dirp, arg2, ret);
|
|
- if (arg4)
|
|
- if (put_user(nbytes, arg4, abi_ulong))
|
|
+ if (arg4) {
|
|
+ if (put_user(basep, arg4, abi_ulong))
|
|
ret = -TARGET_EFAULT;
|
|
+ }
|
|
}
|
|
break;
|
|
|
|
@@ -5431,32 +5852,406 @@ abi_long do_freebsd_syscall(void *cpu_env, int num, abi_long arg1,
|
|
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:
|
|
+ {
|
|
+ struct acl host_acl;
|
|
+
|
|
+ ret = target_to_host_acl(&host_acl, arg3);
|
|
+ if (!is_error(ret))
|
|
+ ret = get_errno(__acl_aclcheck_fd(arg1, arg2,
|
|
+ &host_acl));
|
|
+ }
|
|
+ break;
|
|
+
|
|
+ case TARGET_FREEBSD_NR___acl_aclcheck_file:
|
|
+ {
|
|
+ struct acl host_acl;
|
|
+
|
|
+ if (!(p = lock_user_string(arg1)))
|
|
+ goto efault;
|
|
+
|
|
+ ret = target_to_host_acl(&host_acl, arg3);
|
|
+ if (!is_error(ret))
|
|
+ ret = get_errno(__acl_aclcheck_file(path(p) , arg2,
|
|
+ &host_acl));
|
|
+
|
|
+ unlock_user(p, arg1, 0);
|
|
+ }
|
|
+ break;
|
|
+
|
|
+ case TARGET_FREEBSD_NR___acl_aclcheck_link:
|
|
+ {
|
|
+ struct acl host_acl;
|
|
+
|
|
+ if (!(p = lock_user_string(arg1)))
|
|
+ goto efault;
|
|
+
|
|
+ ret = target_to_host_acl(&host_acl, arg3);
|
|
+ if (!is_error(ret))
|
|
+ ret = get_errno(__acl_aclcheck_link(path(p), arg2,
|
|
+ &host_acl));
|
|
+
|
|
+ unlock_user(p, arg1, 0);
|
|
+ }
|
|
+ break;
|
|
+
|
|
+ case TARGET_FREEBSD_NR___acl_delete_fd:
|
|
+ ret = get_errno(__acl_delete_fd(arg1, arg2));
|
|
+ break;
|
|
+
|
|
+ case TARGET_FREEBSD_NR___acl_delete_file:
|
|
+ if (!(p = lock_user_string(arg1)))
|
|
+ goto efault;
|
|
+
|
|
+ ret = get_errno(__acl_delete_file(path(p), arg2));
|
|
+
|
|
+ unlock_user(p, arg1, 0);
|
|
+ break;
|
|
+
|
|
+ case TARGET_FREEBSD_NR___acl_delete_link:
|
|
+ if (!(p = lock_user_string(arg1)))
|
|
+ goto efault;
|
|
+
|
|
+ ret = get_errno(__acl_delete_link(path(p), arg2));
|
|
+
|
|
+ unlock_user(p, arg1, 0);
|
|
+ break;
|
|
+
|
|
+ case TARGET_FREEBSD_NR___acl_get_fd:
|
|
+ {
|
|
+ struct acl host_acl;
|
|
+
|
|
+ ret = get_errno(__acl_get_fd(arg1, arg2, &host_acl));
|
|
+
|
|
+ if (!is_error(ret))
|
|
+ ret = host_to_target_acl(arg3, &host_acl);
|
|
+ }
|
|
+ break;
|
|
+
|
|
+ case TARGET_FREEBSD_NR___acl_get_file:
|
|
+ {
|
|
+ struct acl host_acl;
|
|
+
|
|
+ if (!(p = lock_user_string(arg1)))
|
|
+ goto efault;
|
|
+
|
|
+ ret = get_errno(__acl_get_file(path(p), arg2, &host_acl));
|
|
+
|
|
+ if (!is_error(ret))
|
|
+ ret = host_to_target_acl(arg3, &host_acl);
|
|
+
|
|
+ unlock_user(p, arg1, 0);
|
|
+ }
|
|
+ break;
|
|
+
|
|
case TARGET_FREEBSD_NR___acl_get_link:
|
|
+ {
|
|
+ struct acl host_acl;
|
|
+
|
|
+ if (!(p = lock_user_string(arg1)))
|
|
+ goto efault;
|
|
+
|
|
+ ret = get_errno(__acl_get_link(path(p), arg2, &host_acl));
|
|
+
|
|
+ if (!is_error(ret))
|
|
+ ret = host_to_target_acl(arg3, &host_acl);
|
|
+
|
|
+ unlock_user(p, arg1, 0);
|
|
+ }
|
|
+ break;
|
|
+
|
|
+ case TARGET_FREEBSD_NR___acl_set_fd:
|
|
+ {
|
|
+ struct acl host_acl;
|
|
+
|
|
+ if (!(p = lock_user_string(arg1)))
|
|
+ goto efault;
|
|
+
|
|
+ ret = target_to_host_acl(&host_acl, arg3);
|
|
+ if (!is_error(ret))
|
|
+ ret = get_errno(__acl_set_fd(arg1, arg2, &host_acl));
|
|
+
|
|
+ unlock_user(p, arg1, 0);
|
|
+ }
|
|
+ break;
|
|
+
|
|
+ case TARGET_FREEBSD_NR___acl_set_file:
|
|
+ {
|
|
+ struct acl host_acl;
|
|
+
|
|
+ if (!(p = lock_user_string(arg1)))
|
|
+ goto efault;
|
|
+
|
|
+ ret = target_to_host_acl(&host_acl, arg3);
|
|
+ if (!is_error(ret))
|
|
+ ret = get_errno(__acl_set_file(path(p), arg2,
|
|
+ &host_acl));
|
|
+
|
|
+ unlock_user(p, arg1, 0);
|
|
+ }
|
|
+ break;
|
|
+
|
|
case TARGET_FREEBSD_NR___acl_set_link:
|
|
- case TARGET_FREEBSD_NR___acl_delete_link:
|
|
- case TARGET_FREEBSD_NR___acl_aclcheck_link:
|
|
+ {
|
|
+ struct acl host_acl;
|
|
+
|
|
+ if (!(p = lock_user_string(arg1)))
|
|
+ goto efault;
|
|
+
|
|
+ ret = target_to_host_acl(&host_acl, arg3);
|
|
+ if (!is_error(ret))
|
|
+ ret = get_errno(__acl_set_link(path(p), arg2,
|
|
+ &host_acl));
|
|
+
|
|
+ unlock_user(p, arg1, 0);
|
|
+ }
|
|
+ break;
|
|
+
|
|
case TARGET_FREEBSD_NR_extattrctl:
|
|
+ {
|
|
+ void *a, *f;
|
|
+
|
|
+ if (!(p = lock_user_string(arg1)))
|
|
+ goto efault;
|
|
+ if (!(f = lock_user_string(arg3)))
|
|
+ goto efault;
|
|
+ if (!(a = lock_user_string(arg5)))
|
|
+ goto efault;
|
|
+
|
|
+ ret = get_errno(extattrctl(path(p), arg2, f, arg4, a));
|
|
+
|
|
+ unlock_user(a, arg5, 0);
|
|
+ unlock_user(f, arg3, 0);
|
|
+ unlock_user(p, arg1, 0);
|
|
+ }
|
|
+ break;
|
|
+
|
|
case TARGET_FREEBSD_NR_extattr_set_file:
|
|
+ {
|
|
+ void *a, *d;
|
|
+
|
|
+ if (!(p = lock_user_string(arg1)))
|
|
+ goto efault;
|
|
+ if (!(a = lock_user_string(arg3)))
|
|
+ goto efault;
|
|
+ if (!(d = lock_user(VERIFY_READ, arg4, arg5, 1)))
|
|
+ goto efault;
|
|
+
|
|
+ ret = get_errno(extattr_set_file(path(p), arg2, a, d, arg5));
|
|
+
|
|
+ unlock_user(d, arg4, arg5);
|
|
+ unlock_user(a, arg3, 0);
|
|
+ unlock_user(p, arg1, 0);
|
|
+ }
|
|
+ break;
|
|
+
|
|
case TARGET_FREEBSD_NR_extattr_get_file:
|
|
+ {
|
|
+ void *a, *d;
|
|
+
|
|
+ if (!(p = lock_user_string(arg1)))
|
|
+ goto efault;
|
|
+ if (!(a = lock_user_string(arg3)))
|
|
+ goto efault;
|
|
+
|
|
+ if (arg4 && arg5 > 0) {
|
|
+ if (!(d = lock_user(VERIFY_WRITE, arg4, arg5, 0)))
|
|
+ goto efault;
|
|
+ ret = get_errno(extattr_get_file(path(p), arg2, a, d,
|
|
+ arg5));
|
|
+ unlock_user(d, arg4, arg5);
|
|
+ } else {
|
|
+ ret = get_errno(extattr_get_file(path(p), arg2, a,
|
|
+ NULL, arg5));
|
|
+ }
|
|
+ unlock_user(a, arg3, 0);
|
|
+ unlock_user(p, arg1, 0);
|
|
+ }
|
|
+ break;
|
|
+
|
|
case TARGET_FREEBSD_NR_extattr_delete_file:
|
|
+ {
|
|
+ void *a;
|
|
+
|
|
+ if (!(p = lock_user_string(arg1)))
|
|
+ goto efault;
|
|
+ if (!(a = lock_user_string(arg3)))
|
|
+ goto efault;
|
|
+
|
|
+ ret = get_errno(extattr_delete_file(path(p), arg2, a));
|
|
+
|
|
+ unlock_user(a, arg3, 0);
|
|
+ unlock_user(p, arg1, 0);
|
|
+ }
|
|
+ break;
|
|
+
|
|
case TARGET_FREEBSD_NR_extattr_set_fd:
|
|
+ {
|
|
+ void *a, *d;
|
|
+
|
|
+ if (!(a = lock_user_string(arg3)))
|
|
+ goto efault;
|
|
+ if (!(d = lock_user(VERIFY_READ, arg4, arg5, 1)))
|
|
+ goto efault;
|
|
+
|
|
+ ret = get_errno(extattr_set_fd(arg1, arg2, a, d, arg5));
|
|
+
|
|
+ unlock_user(d, arg4, arg5);
|
|
+ unlock_user(a, arg3, 0);
|
|
+ }
|
|
+ break;
|
|
+
|
|
case TARGET_FREEBSD_NR_extattr_get_fd:
|
|
+ {
|
|
+ void *a, *d;
|
|
+
|
|
+ if (!(a = lock_user_string(arg3)))
|
|
+ goto efault;
|
|
+
|
|
+ if (arg4 && arg5 > 0) {
|
|
+ if (!(d = lock_user(VERIFY_WRITE, arg4, arg5, 0)))
|
|
+ goto efault;
|
|
+ ret = get_errno(extattr_get_fd(arg1, arg2, a, d,
|
|
+ arg5));
|
|
+ unlock_user(d, arg4, arg5);
|
|
+ } else {
|
|
+ ret = get_errno(extattr_get_fd(arg1, arg2, a,
|
|
+ NULL, arg5));
|
|
+ }
|
|
+ unlock_user(a, arg3, 0);
|
|
+ }
|
|
+ break;
|
|
+
|
|
case TARGET_FREEBSD_NR_extattr_delete_fd:
|
|
+ {
|
|
+ void *a;
|
|
+
|
|
+ if (!(a = lock_user_string(arg3)))
|
|
+ goto efault;
|
|
+
|
|
+ ret = get_errno(extattr_delete_fd(arg1, arg2, a));
|
|
+
|
|
+ unlock_user(a, arg3, 0);
|
|
+ }
|
|
+ break;
|
|
+
|
|
case TARGET_FREEBSD_NR_extattr_get_link:
|
|
+ {
|
|
+ void *a, *d;
|
|
+
|
|
+ if (!(p = lock_user_string(arg1)))
|
|
+ goto efault;
|
|
+ if (!(a = lock_user_string(arg3)))
|
|
+ goto efault;
|
|
+
|
|
+ if (arg4 && arg5 > 0) {
|
|
+ if (!(d = lock_user(VERIFY_WRITE, arg4, arg5, 0)))
|
|
+ goto efault;
|
|
+ ret = get_errno(extattr_get_link(path(p), arg2, a, d,
|
|
+ arg5));
|
|
+ unlock_user(d, arg4, arg5);
|
|
+ } else {
|
|
+ ret = get_errno(extattr_get_link(path(p), arg2, a,
|
|
+ NULL, arg5));
|
|
+ }
|
|
+ unlock_user(a, arg3, 0);
|
|
+ unlock_user(p, arg1, 0);
|
|
+ }
|
|
+ break;
|
|
+
|
|
case TARGET_FREEBSD_NR_extattr_set_link:
|
|
+ {
|
|
+ void *a, *d;
|
|
+
|
|
+ if (!(p = lock_user_string(arg1)))
|
|
+ goto efault;
|
|
+ if (!(a = lock_user_string(arg3)))
|
|
+ goto efault;
|
|
+ if (!(d = lock_user(VERIFY_READ, arg4, arg5, 1)))
|
|
+ goto efault;
|
|
+
|
|
+ ret = get_errno(extattr_set_link(path(p), arg2, a, d, arg5));
|
|
+
|
|
+ unlock_user(d, arg4, arg5);
|
|
+ unlock_user(a, arg3, 0);
|
|
+ unlock_user(p, arg1, 0);
|
|
+ }
|
|
+ break;
|
|
+
|
|
case TARGET_FREEBSD_NR_extattr_delete_link:
|
|
+ {
|
|
+ void *a;
|
|
+
|
|
+ if (!(p = lock_user_string(arg1)))
|
|
+ goto efault;
|
|
+ if (!(a = lock_user_string(arg3)))
|
|
+ goto efault;
|
|
+
|
|
+ ret = get_errno(extattr_delete_link(path(p), arg2, a));
|
|
+
|
|
+ unlock_user(a, arg3, 0);
|
|
+ unlock_user(p, arg1, 0);
|
|
+ }
|
|
+ break;
|
|
+
|
|
case TARGET_FREEBSD_NR_extattr_list_fd:
|
|
+ {
|
|
+ void *d;
|
|
+
|
|
+ if (arg3 && arg4 > 0) {
|
|
+ if (!(d = lock_user(VERIFY_WRITE, arg3, arg4, 0)))
|
|
+ goto efault;
|
|
+ ret = get_errno(extattr_list_fd(arg1, arg2, d,
|
|
+ arg4));
|
|
+ unlock_user(d, arg3, arg4);
|
|
+ } else {
|
|
+ ret = get_errno(extattr_list_fd(arg1, arg2,
|
|
+ NULL, arg4));
|
|
+ }
|
|
+ }
|
|
+ break;
|
|
+
|
|
case TARGET_FREEBSD_NR_extattr_list_file:
|
|
+ {
|
|
+ void *d;
|
|
+
|
|
+ if (!(p = lock_user_string(arg1)))
|
|
+ goto efault;
|
|
+
|
|
+ if (arg3 && arg4 > 0) {
|
|
+ if (!(d = lock_user(VERIFY_WRITE, arg3, arg4, 0)))
|
|
+ goto efault;
|
|
+ ret = get_errno(extattr_list_file(path(p), arg2, d,
|
|
+ arg4));
|
|
+ unlock_user(d, arg3, arg4);
|
|
+ } else {
|
|
+ ret = get_errno(extattr_list_file(path(p), arg2,
|
|
+ NULL, arg4));
|
|
+ }
|
|
+ unlock_user(p, arg1, 0);
|
|
+ }
|
|
+ break;
|
|
+
|
|
case TARGET_FREEBSD_NR_extattr_list_link:
|
|
- ret = unimplemented(num);
|
|
+ {
|
|
+ void *d;
|
|
+
|
|
+ if (!(p = lock_user_string(arg1)))
|
|
+ goto efault;
|
|
+
|
|
+ if (arg3 && arg4 > 0) {
|
|
+ if (!(d = lock_user(VERIFY_WRITE, arg3, arg4, 0)))
|
|
+ goto efault;
|
|
+ ret = get_errno(extattr_list_link(path(p), arg2, d,
|
|
+ arg4));
|
|
+ unlock_user(d, arg3, arg4);
|
|
+ } else {
|
|
+ ret = get_errno(extattr_list_link(path(p), arg2,
|
|
+ NULL, arg4));
|
|
+ }
|
|
+
|
|
+ unlock_user(p, arg1, 0);
|
|
+ }
|
|
break;
|
|
|
|
case TARGET_FREEBSD_NR_setlogin:
|
|
@@ -5635,6 +6430,10 @@ abi_long do_freebsd_syscall(void *cpu_env, int num, abi_long arg1,
|
|
ret = do_semctl(arg1, arg2, arg3, (union target_semun)(abi_ulong)arg4);
|
|
break;
|
|
|
|
+ case TARGET_FREEBSD_NR_freebsd7___semctl:
|
|
+ ret = unimplemented(num);
|
|
+ break;
|
|
+
|
|
case TARGET_FREEBSD_NR_msgctl:
|
|
ret = do_msgctl(arg1, arg2, arg3);
|
|
break;
|
|
@@ -5715,7 +6514,7 @@ abi_long do_freebsd_syscall(void *cpu_env, int num, abi_long arg1,
|
|
break;
|
|
|
|
case TARGET_FREEBSD_NR_seteuid:
|
|
- ret = get_errno(setegid(arg1));
|
|
+ ret = get_errno(seteuid(arg1));
|
|
break;
|
|
|
|
case TARGET_FREEBSD_NR_getpgrp:
|
|
@@ -6953,7 +7752,7 @@ void syscall_init(void)
|
|
|
|
#define STRUCT(name, ...) thunk_register_struct(STRUCT_ ## name, #name, struct_ ## name ## _def);
|
|
#define STRUCT_SPECIAL(name) thunk_register_struct_direct(STRUCT_ ## name, #name, &struct_ ## name ## _def);
|
|
-#ifdef __FreeBSD__
|
|
+#if defined(__FreeBSD__)
|
|
#include "freebsd/syscall_types.h"
|
|
#else
|
|
#warning No syscall_types.h
|
|
diff --git a/bsd-user/syscall_defs.h b/bsd-user/syscall_defs.h
|
|
index 3eb760b..8a92403 100644
|
|
--- a/bsd-user/syscall_defs.h
|
|
+++ b/bsd-user/syscall_defs.h
|
|
@@ -203,12 +203,12 @@ struct target_pollfd {
|
|
#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;
|
|
+ abi_long l_start;
|
|
+ abi_long l_len;
|
|
+ int32_t l_pid;
|
|
+ int16_t l_type;
|
|
+ int16_t l_whence;
|
|
+ int32_t l_sysid;
|
|
} QEMU_PACKED;
|
|
|
|
struct target_iovec {
|
|
@@ -451,6 +451,7 @@ typedef struct target_siginfo {
|
|
int32_t si_code; /* signal code */
|
|
int32_t si_pid; /* sending process */
|
|
int32_t si_uid; /* sender's ruid */
|
|
+ int32_t si_status; /* exit value */
|
|
abi_ulong si_addr; /* faulting instruction */
|
|
|
|
union target_sigval si_value; /* signal value */
|
|
@@ -756,3 +757,41 @@ struct target_timex {
|
|
struct target_sched_param {
|
|
int32_t sched_priority;
|
|
};
|
|
+
|
|
+
|
|
+/*
|
|
+ * sys/acl.h
|
|
+ */
|
|
+
|
|
+#define TARGET_ACL_MAX_ENTRIES 254
|
|
+
|
|
+struct target_acl_entry {
|
|
+ int32_t ae_tag;
|
|
+ uint32_t ae_id;
|
|
+ uint16_t ae_perm;
|
|
+ uint16_t ae_entry_type;
|
|
+ uint16_t ae_flags;
|
|
+};
|
|
+
|
|
+struct target_acl {
|
|
+ uint32_t acl_maxcnt;
|
|
+ uint32_t acl_cnt;
|
|
+ int32_t acl_space[4];
|
|
+ struct target_acl_entry acl_entry[TARGET_ACL_MAX_ENTRIES];
|
|
+};
|
|
+
|
|
+
|
|
+/*
|
|
+ * netinet/in.h
|
|
+ */
|
|
+
|
|
+struct target_ip_mreq {
|
|
+ struct target_in_addr imr_multiaddr;
|
|
+ struct target_in_addr imr_interface;
|
|
+};
|
|
+
|
|
+struct target_ip_mreqn {
|
|
+ struct target_in_addr imr_multiaddr;
|
|
+ struct target_in_addr imr_address;
|
|
+ int32_t imr_ifindex;
|
|
+};
|
|
diff --git a/configure b/configure
|
|
index d99584d..6d17c97 100755
|
|
--- a/configure
|
|
+++ b/configure
|
|
@@ -434,8 +434,9 @@ FreeBSD)
|
|
make="${MAKE-gmake}"
|
|
audio_drv_list="oss"
|
|
audio_possible_drivers="oss sdl esd pa"
|
|
- # needed for kinfo_getvmmap(3) in libutil.h
|
|
- LIBS="-lutil $LIBS"
|
|
+ # -lutil needed for kinfo_getvmmap(3) in libutil.h
|
|
+ # -lprocstat needed for procstat_*(3) in main.c
|
|
+ LIBS="-lprocstat -lutil $LIBS"
|
|
;;
|
|
DragonFly)
|
|
bsd="yes"
|
|
@@ -1237,6 +1238,11 @@ if test "$static" = "yes" ; then
|
|
else
|
|
pie="no"
|
|
fi
|
|
+ if test "$bsd" = "yes" ; then
|
|
+ # Missing libs when linking statically
|
|
+ LIBS="$LIBS -lintl -lkvm"
|
|
+ libs_qga="-lintl $libs_qga"
|
|
+ fi
|
|
fi
|
|
|
|
if test "$pie" = ""; then
|
|
diff --git a/util/aes.c b/util/aes.c
|
|
index 1da7bff..30a6608 100644
|
|
--- a/util/aes.c
|
|
+++ b/util/aes.c
|
|
@@ -877,6 +877,7 @@ int AES_set_decrypt_key(const unsigned char *userKey, const int bits,
|
|
return 0;
|
|
}
|
|
|
|
+#if defined(CONFIG_STATIC) && ! defined(__FreeBSD__)
|
|
#ifndef AES_ASM
|
|
/*
|
|
* Encrypt a single block
|
|
@@ -1312,3 +1313,4 @@ void AES_cbc_encrypt(const unsigned char *in, unsigned char *out,
|
|
}
|
|
}
|
|
}
|
|
+#endif /* CONFIG_STATIC && ! __FreeBSD__ */
|