diff -ruN /home/ogra/Devel/packages/qemu-0.10.5/linux-user/ioctls.h ./linux-user/ioctls.h --- /home/ogra/Devel/packages/qemu-0.10.5/linux-user/ioctls.h 2009-05-20 22:46:59.000000000 +0200 +++ ./linux-user/ioctls.h 2009-07-17 08:28:45.000000000 +0200 @@ -74,7 +74,7 @@ IOCTL(FIGETBSZ, IOC_R, MK_PTR(TYPE_LONG)) #endif - IOCTL(SIOCATMARK, 0, TYPE_NULL) + IOCTL(SIOCATMARK, 0, MK_PTR(TYPE_INT)) IOCTL(SIOCADDRT, IOC_W, MK_PTR(MK_STRUCT(STRUCT_rtentry))) IOCTL(SIOCDELRT, IOC_W, MK_PTR(MK_STRUCT(STRUCT_rtentry))) IOCTL(SIOCGIFNAME, IOC_RW, MK_PTR(TYPE_INT)) diff -ruN /home/ogra/Devel/packages/qemu-0.10.5/linux-user/main.c ./linux-user/main.c --- /home/ogra/Devel/packages/qemu-0.10.5/linux-user/main.c 2009-05-20 22:46:59.000000000 +0200 +++ ./linux-user/main.c 2009-07-17 08:29:22.000000000 +0200 @@ -1004,7 +1004,7 @@ default: printf ("Unhandled trap: 0x%x\n", trapnr); cpu_dump_state(env, stderr, fprintf, 0); - exit (1); + _exit (1); } process_pending_signals (env); } @@ -1933,7 +1933,7 @@ default: printf ("Unhandled trap: 0x%x\n", trapnr); cpu_dump_state(env, stderr, fprintf, 0); - exit (1); + _exit (1); } process_pending_signals (env); } @@ -2240,6 +2240,7 @@ TaskState ts1, *ts = &ts1; CPUState *env; int optind; + int argskip=0; const char *r; int gdbstub_port = 0; char **target_environ, **wrk; @@ -2289,7 +2290,7 @@ for(item = cpu_log_items; item->mask != 0; item++) { printf("%-10s %s\n", item->name, item->help); } - exit(1); + _exit(1); } cpu_set_log(mask); } else if (!strcmp(r, "E")) { @@ -2320,8 +2321,10 @@ if (qemu_host_page_size == 0 || (qemu_host_page_size & (qemu_host_page_size - 1)) != 0) { fprintf(stderr, "page size must be a power of two\n"); - exit(1); + _exit(1); } + } else if (!strcmp(r,"-sbox-call")) { + argskip++; } else if (!strcmp(r, "g")) { if (optind >= argc) break; @@ -2368,7 +2371,7 @@ cpu_model = "qemu32"; #endif #elif defined(TARGET_ARM) - cpu_model = "arm926"; + cpu_model = "any"; #elif defined(TARGET_M68K) cpu_model = "any"; #elif defined(TARGET_SPARC) @@ -2410,7 +2413,7 @@ target_environ = envlist_to_environ(envlist, NULL); envlist_free(envlist); - if (loader_exec(filename, argv+optind, target_environ, regs, info) != 0) { + if (loader_exec(filename, argv+optind+argskip, target_environ, regs, info) != 0) { printf("Error loading %s\n", filename); _exit(1); } diff -ruN /home/ogra/Devel/packages/qemu-0.10.5/linux-user/signal.c ./linux-user/signal.c --- /home/ogra/Devel/packages/qemu-0.10.5/linux-user/signal.c 2009-05-20 22:46:59.000000000 +0200 +++ ./linux-user/signal.c 2009-07-17 08:28:54.000000000 +0200 @@ -25,6 +25,7 @@ #include #include #include +#include #include #include "qemu.h" diff -ruN /home/ogra/Devel/packages/qemu-0.10.5/linux-user/syscall.c ./linux-user/syscall.c --- /home/ogra/Devel/packages/qemu-0.10.5/linux-user/syscall.c 2009-05-20 22:46:59.000000000 +0200 +++ ./linux-user/syscall.c 2009-07-17 08:28:51.000000000 +0200 @@ -44,12 +44,14 @@ #include #include #include +#include #include #include #include #include #include #include +#include #include //#include #include @@ -299,6 +301,7 @@ extern int setfsuid(int); extern int setfsgid(int); extern int setgroups(int, gid_t *); +extern int uselib(const char*); #define ERRNO_TABLE_SIZE 1200 @@ -690,14 +693,17 @@ static inline abi_long target_to_host_sockaddr(struct sockaddr *addr, abi_ulong target_addr, - socklen_t len) + socklen_t *target_len) { + const socklen_t len = sizeof (struct sockaddr_un); struct target_sockaddr *target_saddr; - target_saddr = lock_user(VERIFY_READ, target_addr, len, 1); + target_saddr = lock_user(VERIFY_READ, target_addr, *target_len, 1); if (!target_saddr) return -TARGET_EFAULT; - memcpy(addr, target_saddr, len); + if (target_saddr->sa_family == AF_UNIX && *target_len > len) + *target_len = len; + memcpy(addr, target_saddr, *target_len); addr->sa_family = tswap16(target_saddr->sa_family); unlock_user(target_saddr, target_addr, 0); @@ -833,6 +839,32 @@ return 0; } +static inline abi_long host_to_target_linger(target_ulong target_addr, + struct linger *host_l) +{ + struct target_linger *target_l; + + if (!lock_user_struct(VERIFY_WRITE, target_l, target_addr, 0)) + return -TARGET_EFAULT; + target_l->l_onoff = tswapl(host_l->l_onoff); + target_l->l_linger = tswapl(host_l->l_linger); + unlock_user_struct(target_l, target_addr, 1); + return 0; +} + +static inline abi_long target_to_host_linger(struct linger *host_l, + target_ulong target_addr) +{ + struct target_linger *target_l; + + if (!lock_user_struct(VERIFY_WRITE, target_l, target_addr, 1)) + return -TARGET_EFAULT; + host_l->l_onoff = tswapl(target_l->l_onoff); + host_l->l_linger = tswapl(target_l->l_linger); + unlock_user_struct(target_l, target_addr, 0); + return 0; +} + /* do_setsockopt() Must return target values and target errnos. */ static abi_long do_setsockopt(int sockfd, int level, int optname, abi_ulong optval_addr, socklen_t optlen) @@ -883,7 +915,6 @@ break; case TARGET_SOL_SOCKET: switch (optname) { - /* Options with 'int' argument. */ case TARGET_SO_DEBUG: optname = SO_DEBUG; break; @@ -940,16 +971,44 @@ case TARGET_SO_SNDTIMEO: optname = SO_SNDTIMEO; break; - break; + case TARGET_SO_LINGER: + optname = SO_LINGER; + break; default: goto unimplemented; } - if (optlen < sizeof(uint32_t)) - return -TARGET_EINVAL; - - if (get_user_u32(val, optval_addr)) - return -TARGET_EFAULT; - ret = get_errno(setsockopt(sockfd, SOL_SOCKET, optname, &val, sizeof(val))); + switch (optname) { + /* Options with non-'int' argument. */ + case SO_RCVTIMEO: + case SO_SNDTIMEO: + { + struct timeval tval; + if(optlen < sizeof(struct target_timeval)) + return -TARGET_EINVAL; + copy_from_user_timeval(&tval,optval_addr); + ret = get_errno(setsockopt(sockfd, level, optname, &tval,sizeof(tval))); + } + break; + case SO_LINGER: + { + struct linger tmp; + if (optlen < sizeof(struct target_linger)) + return -TARGET_EINVAL; + optname = SO_LINGER; + target_to_host_linger(&tmp,optval_addr); + ret = get_errno(setsockopt(sockfd, level, optname, &tmp, sizeof(tmp))); + } + break; + /* All remaning options take an 'int' argument. */ + default: + { + if (optlen < sizeof(uint32_t)) + return -TARGET_EINVAL; + val = get_user_u32(val, optval_addr); + ret = get_errno(setsockopt(sockfd, SOL_SOCKET, optname, &val, sizeof(val))); + } + break; + } break; default: unimplemented: @@ -971,10 +1030,55 @@ case TARGET_SOL_SOCKET: level = SOL_SOCKET; switch (optname) { - case TARGET_SO_LINGER: + case TARGET_SO_LINGER: { + if (get_user_u32(len, optlen)) + return -TARGET_EFAULT; + if(len < sizeof(struct target_linger)) + return -TARGET_EINVAL; + struct linger l; + len=sizeof(l); + + ret = get_errno(getsockopt(sockfd, level, optname, &l, &len)); + host_to_target_linger(optval_addr,&l); + if (put_user_u32(sizeof(struct target_linger), optlen)) + return -TARGET_EFAULT; + } + break; + case TARGET_SO_RCVTIMEO: - case TARGET_SO_SNDTIMEO: - case TARGET_SO_PEERCRED: + case TARGET_SO_SNDTIMEO: { + if (get_user_u32(len, optlen)) + return -TARGET_EFAULT; + + if(len < sizeof(struct target_timeval)) + return -TARGET_EINVAL; + struct timeval tval; + len=sizeof(tval); + + ret = get_errno(getsockopt(sockfd, level, optname, &tval, &len)); + if (copy_to_user_timeval(optval_addr,&tval)) + return -TARGET_EFAULT; + + if (put_user_u32(sizeof(struct target_timeval), optlen)) + return -TARGET_EFAULT; + } + break; + + case TARGET_SO_PEERCRED: { + struct ucred caller; + socklen_t optlen = sizeof (caller); + ret = get_errno(getsockopt(sockfd, SOL_SOCKET, SO_PEERCRED, + &caller, &optlen)); + + if (optlen != 0 && optval_addr != 0) { + if (put_user_u32(caller.pid, optval_addr + 0) || + put_user_u32(caller.uid, optval_addr + 4) || + put_user_u32(caller.gid, optval_addr + 8)) + return -TARGET_EFAULT; + } + } + break; + case TARGET_SO_PEERNAME: /* These don't just return a single integer */ goto unimplemented; @@ -1154,7 +1258,7 @@ addr = alloca(addrlen); - target_to_host_sockaddr(addr, target_addr, addrlen); + target_to_host_sockaddr(addr, target_addr, &addrlen); return get_errno(bind(sockfd, addr, addrlen)); } @@ -1169,7 +1273,7 @@ addr = alloca(addrlen); - target_to_host_sockaddr(addr, target_addr, addrlen); + target_to_host_sockaddr(addr, target_addr, &addrlen); return get_errno(connect(sockfd, addr, addrlen)); } @@ -1193,8 +1297,10 @@ if (msgp->msg_name) { msg.msg_namelen = tswap32(msgp->msg_namelen); msg.msg_name = alloca(msg.msg_namelen); - target_to_host_sockaddr(msg.msg_name, tswapl(msgp->msg_name), - msg.msg_namelen); + ret = target_to_host_sockaddr(msg.msg_name, tswapl(msgp->msg_name), + &msg.msg_namelen); + if (is_error(ret)) + goto fail; } else { msg.msg_name = NULL; msg.msg_namelen = 0; @@ -1224,6 +1330,7 @@ } } unlock_iovec(vec, target_vec, count, !send); +fail: unlock_user_struct(msgp, target_msg, send ? 0 : 1); return ret; } @@ -1237,7 +1344,10 @@ abi_long ret; if (get_user_u32(addrlen, target_addrlen_addr)) - return -TARGET_EFAULT; + return -TARGET_EINVAL; + + if (addrlen < 0 || addrlen > MAX_SOCK_ADDR) + return -TARGET_EINVAL; if (addrlen < 0 || addrlen > MAX_SOCK_ADDR) return -TARGET_EINVAL; @@ -1267,12 +1377,15 @@ if (addrlen < 0 || addrlen > MAX_SOCK_ADDR) return -TARGET_EINVAL; + if (addrlen < 0 || addrlen > MAX_SOCK_ADDR) + return -TARGET_EINVAL; + addr = alloca(addrlen); ret = get_errno(getpeername(fd, addr, &addrlen)); if (!is_error(ret)) { - host_to_target_sockaddr(target_addr, addr, addrlen); - if (put_user_u32(addrlen, target_addrlen_addr)) + if ((host_to_target_sockaddr(target_addr, addr, addrlen) < 0) || + (put_user_u32(addrlen, target_addrlen_addr))) ret = -TARGET_EFAULT; } return ret; @@ -1299,8 +1412,8 @@ ret = get_errno(getsockname(fd, addr, &addrlen)); if (!is_error(ret)) { - host_to_target_sockaddr(target_addr, addr, addrlen); - if (put_user_u32(addrlen, target_addrlen_addr)) + if ((host_to_target_sockaddr(target_addr, addr, addrlen) < 0) || + (put_user_u32(addrlen, target_addrlen_addr))) ret = -TARGET_EFAULT; } return ret; @@ -1333,13 +1446,17 @@ if (addrlen < 0 || addrlen > MAX_SOCK_ADDR) return -TARGET_EINVAL; + if (addrlen < 0 || addrlen > MAX_SOCK_ADDR) + return -TARGET_EINVAL; + host_msg = lock_user(VERIFY_READ, msg, len, 1); if (!host_msg) return -TARGET_EFAULT; if (target_addr) { addr = alloca(addrlen); - target_to_host_sockaddr(addr, target_addr, addrlen); - ret = get_errno(sendto(fd, host_msg, len, flags, addr, addrlen)); + ret = target_to_host_sockaddr(addr, target_addr, &addrlen); + if (!is_error(ret)) + ret = get_errno(sendto(fd, host_msg, len, flags, addr, addrlen)); } else { ret = get_errno(send(fd, host_msg, len, flags)); } @@ -1369,6 +1486,10 @@ ret = -TARGET_EINVAL; goto fail; } + if (addrlen < 0 || addrlen > MAX_SOCK_ADDR) { + ret = -TARGET_EINVAL; + goto fail; + } addr = alloca(addrlen); ret = get_errno(recvfrom(fd, host_msg, len, flags, addr, &addrlen)); } else { @@ -2856,6 +2977,7 @@ pthread_cond_t cond; pthread_t thread; uint32_t tid; + unsigned int flags; abi_ulong child_tidptr; abi_ulong parent_tidptr; sigset_t sigmask; @@ -2869,9 +2991,11 @@ env = info->env; thread_env = env; info->tid = gettid(); - if (info->child_tidptr) + if (info->flags & CLONE_CHILD_SETTID) put_user_u32(info->tid, info->child_tidptr); - if (info->parent_tidptr) + if (info->flags & CLONE_CHILD_CLEARTID) + set_tid_address(g2h(info->child_tidptr)); + if (info->flags & CLONE_PARENT_SETTID) put_user_u32(info->tid, info->parent_tidptr); /* Enable signals. */ sigprocmask(SIG_SETMASK, &info->sigmask, NULL); @@ -2936,7 +3060,6 @@ nptl_flags = flags; flags &= ~CLONE_NPTL_FLAGS2; - /* TODO: Implement CLONE_CHILD_CLEARTID. */ if (nptl_flags & CLONE_SETTLS) cpu_set_tls (new_env, newtls); @@ -2948,7 +3071,9 @@ pthread_mutex_lock(&info.mutex); pthread_cond_init(&info.cond, NULL); info.env = new_env; - if (nptl_flags & CLONE_CHILD_SETTID) + info.flags = nptl_flags; + if (nptl_flags & CLONE_CHILD_SETTID || + nptl_flags & CLONE_CHILD_CLEARTID) info.child_tidptr = child_tidptr; if (nptl_flags & CLONE_PARENT_SETTID) info.parent_tidptr = parent_tidptr; @@ -4446,7 +4571,8 @@ #endif #ifdef TARGET_NR_uselib case TARGET_NR_uselib: - goto unimplemented; + ret = get_errno(uselib(path((const char*)arg1))); + break; #endif #ifdef TARGET_NR_swapon case TARGET_NR_swapon: @@ -5191,9 +5317,35 @@ break; #endif case TARGET_NR__sysctl: - /* We don't implement this, but ENOTDIR is always a safe - return value. */ - ret = -TARGET_ENOTDIR; + { + struct __sysctl_args *args = (struct __sysctl_args *) arg1; + int *name_target, *name, nlen, *oldlenp, oldlen, newlen, i; + void *oldval, *newval; + + name_target = (int *) tswapl((long) args->name); + nlen = tswapl(args->nlen); + oldval = (void *) tswapl((long) args->oldval); + oldlenp = (int *) tswapl((long) args->oldlenp); + oldlen = tswapl(*oldlenp); + newval = (void *) tswapl((long) args->newval); + newlen = tswapl(args->newlen); + + name = alloca(nlen * sizeof (int)); + for (i = 0; i < nlen; i++) + name[i] = tswapl(name_target[i]); + + if (nlen == 2 && name[0] == CTL_KERN && name[1] == KERN_VERSION) { + ret = get_errno( + sysctl(name, nlen, oldval, &oldlen, newval, newlen)); + if (!is_error(ret)) { + *oldlenp = tswapl(oldlen); + } + } else { + gemu_log("qemu: Unsupported sysctl name\n"); + ret = -ENOSYS; + } + } + break; break; case TARGET_NR_sched_setparam: { @@ -6051,9 +6203,15 @@ #if defined(TARGET_NR_utimensat) && defined(__NR_utimensat) case TARGET_NR_utimensat: { - struct timespec ts[2]; - target_to_host_timespec(ts, arg3); - target_to_host_timespec(ts+1, arg3+sizeof(struct target_timespec)); + struct timespec * ts = NULL; + + if (arg3) { + struct timespec ts_[2]; + ts = ts_; + target_to_host_timespec(ts, arg3); + target_to_host_timespec(ts+1, arg3+sizeof(struct target_timespec)); + } + if (!arg2) ret = get_errno(sys_utimensat(arg1, NULL, ts, arg4)); else { diff -ruN /home/ogra/Devel/packages/qemu-0.10.5/linux-user/syscall_defs.h ./linux-user/syscall_defs.h --- /home/ogra/Devel/packages/qemu-0.10.5/linux-user/syscall_defs.h 2009-05-20 22:46:59.000000000 +0200 +++ ./linux-user/syscall_defs.h 2009-07-17 08:28:13.000000000 +0200 @@ -114,6 +114,11 @@ abi_long tv_nsec; }; +struct target_linger { + target_long l_onoff; + target_long l_linger; +}; + struct target_itimerval { struct target_timeval it_interval; struct target_timeval it_value; diff -ruN /home/ogra/Devel/packages/qemu-0.10.5/target-arm/translate.c ./target-arm/translate.c --- /home/ogra/Devel/packages/qemu-0.10.5/target-arm/translate.c 2009-05-20 22:47:00.000000000 +0200 +++ ./target-arm/translate.c 2009-07-17 08:28:13.000000000 +0200 @@ -5757,7 +5757,7 @@ } } else if ((insn & 0x0e5fffe0) == 0x084d0500) { /* srs */ - uint32_t offset; + int32_t offset; if (IS_USER(s)) goto illegal_op; ARCH(6); @@ -5771,8 +5771,8 @@ i = (insn >> 23) & 3; switch (i) { case 0: offset = -4; break; /* DA */ - case 1: offset = -8; break; /* DB */ - case 2: offset = 0; break; /* IA */ + case 1: offset = 0; break; /* IA */ + case 2: offset = -8; break; /* DB */ case 3: offset = 4; break; /* IB */ default: abort(); } @@ -5780,32 +5780,33 @@ tcg_gen_addi_i32(addr, addr, offset); tmp = load_reg(s, 14); gen_st32(tmp, addr, 0); - tmp = new_tmp(); - gen_helper_cpsr_read(tmp); + tmp = load_cpu_field(spsr); tcg_gen_addi_i32(addr, addr, 4); gen_st32(tmp, addr, 0); if (insn & (1 << 21)) { /* Base writeback. */ switch (i) { case 0: offset = -8; break; - case 1: offset = -4; break; - case 2: offset = 4; break; + case 1: offset = 4; break; + case 2: offset = -4; break; case 3: offset = 0; break; default: abort(); } if (offset) - tcg_gen_addi_i32(addr, tmp, offset); + tcg_gen_addi_i32(addr, addr, offset); if (op1 == (env->uncached_cpsr & CPSR_M)) { - gen_movl_reg_T1(s, 13); + store_reg(s, 13, addr); } else { - gen_helper_set_r13_banked(cpu_env, tcg_const_i32(op1), cpu_T[1]); + gen_helper_set_r13_banked(cpu_env, tcg_const_i32(op1), addr); + dead_tmp(addr); } } else { dead_tmp(addr); } + return; } else if ((insn & 0x0e5fffe0) == 0x081d0a00) { /* rfe */ - uint32_t offset; + int32_t offset; if (IS_USER(s)) goto illegal_op; ARCH(6); @@ -5814,8 +5815,8 @@ i = (insn >> 23) & 3; switch (i) { case 0: offset = -4; break; /* DA */ - case 1: offset = -8; break; /* DB */ - case 2: offset = 0; break; /* IA */ + case 1: offset = 0; break; /* IA */ + case 2: offset = -8; break; /* DB */ case 3: offset = 4; break; /* IB */ default: abort(); } @@ -5829,8 +5830,8 @@ /* Base writeback. */ switch (i) { case 0: offset = -8; break; - case 1: offset = -4; break; - case 2: offset = 4; break; + case 1: offset = 4; break; + case 2: offset = -4; break; case 3: offset = 0; break; default: abort(); } @@ -5841,6 +5842,7 @@ dead_tmp(addr); } gen_rfe(s, tmp, tmp2); + return; } else if ((insn & 0x0e000000) == 0x0a000000) { /* branch link and change to thumb (blx ) */ int32_t offset;