ports/emulators/qemu-devel/files/patch-z9c-bsd-user-sson003c
Juergen Lock 45aa9370f0 - Update net/usbredir to 0.6 .
- 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
2013-03-29 17:40:38 +00:00

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__ */