*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
+ * MA 02110-1301, USA.
*/
#include <stdlib.h>
#include <stdio.h>
#include <fcntl.h>
#include <time.h>
#include <limits.h>
-#include <dirent.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#include <netinet/ip.h>
#include <netinet/tcp.h>
#include <qemu-common.h>
+#ifdef HAVE_GPROF
+#include <sys/gmon.h>
+#endif
#define termios host_termios
#define winsize host_winsize
#endif
//#include <linux/msdos_fs.h>
-#define VFAT_IOCTL_READDIR_BOTH _IOR('r', 1, struct dirent [2])
-#define VFAT_IOCTL_READDIR_SHORT _IOR('r', 2, struct dirent [2])
+#define VFAT_IOCTL_READDIR_BOTH _IOR('r', 1, struct linux_dirent [2])
+#define VFAT_IOCTL_READDIR_SHORT _IOR('r', 2, struct linux_dirent [2])
#undef _syscall0
}
+#define __NR_sys_exit __NR_exit
#define __NR_sys_uname __NR_uname
#define __NR_sys_faccessat __NR_faccessat
#define __NR_sys_fchmodat __NR_fchmodat
return -ENOSYS;
}
#endif
+_syscall1(int,sys_exit,int,status)
_syscall1(int,sys_uname,struct new_utsname *,buf)
#if defined(TARGET_NR_faccessat) && defined(__NR_faccessat)
_syscall4(int,sys_faccessat,int,dirfd,const char *,pathname,int,mode,int,flags)
#endif
_syscall2(int,sys_getcwd1,char *,buf,size_t,size)
#if TARGET_ABI_BITS == 32
-_syscall3(int, sys_getdents, uint, fd, struct dirent *, dirp, uint, count);
+_syscall3(int, sys_getdents, uint, fd, struct linux_dirent *, dirp, uint, count);
#endif
#if defined(TARGET_NR_getdents64) && defined(__NR_getdents64)
-_syscall3(int, sys_getdents64, uint, fd, struct dirent64 *, dirp, uint, count);
+_syscall3(int, sys_getdents64, uint, fd, struct linux_dirent64 *, dirp, uint, count);
#endif
_syscall2(int, sys_getpriority, int, which, int, who);
#if !defined (__x86_64__)
{
struct target_iovec *target_vec;
abi_ulong base;
- int i, j;
+ int i;
target_vec = lock_user(VERIFY_READ, target_addr, count * sizeof(struct target_iovec), 1);
if (!target_vec)
vec[i].iov_len = tswapl(target_vec[i].iov_len);
if (vec[i].iov_len != 0) {
vec[i].iov_base = lock_user(type, base, vec[i].iov_len, copy);
- if (!vec[i].iov_base && vec[i].iov_len)
- goto fail;
+ /* Don't check lock_user return value. We must call writev even
+ if a element has invalid base address. */
} else {
/* zero length pointer is ignored */
vec[i].iov_base = NULL;
}
unlock_user (target_vec, target_addr, 0);
return 0;
- fail:
- /* failure - unwind locks */
- for (j = 0; j < i; j++) {
- base = tswapl(target_vec[j].iov_base);
- unlock_user(vec[j].iov_base, base, 0);
- }
- unlock_user (target_vec, target_addr, 0);
- return -TARGET_EFAULT;
}
static abi_long unlock_iovec(struct iovec *vec, abi_ulong target_addr,
if (!target_vec)
return -TARGET_EFAULT;
for(i = 0;i < count; i++) {
- base = tswapl(target_vec[i].iov_base);
- unlock_user(vec[i].iov_base, base, copy ? vec[i].iov_len : 0);
+ if (target_vec[i].iov_base) {
+ base = tswapl(target_vec[i].iov_base);
+ unlock_user(vec[i].iov_base, base, copy ? vec[i].iov_len : 0);
+ }
}
unlock_user (target_vec, target_addr, 0);
static abi_long do_sendrecvmsg(int fd, abi_ulong target_msg,
int flags, int send)
{
- abi_long ret;
+ abi_long ret, len;
struct target_msghdr *msgp;
struct msghdr msg;
int count;
ret = get_errno(sendmsg(fd, &msg, flags));
} else {
ret = get_errno(recvmsg(fd, &msg, flags));
- if (!is_error(ret))
+ if (!is_error(ret)) {
+ len = ret;
ret = host_to_target_cmsg(msgp, &msg);
+ if (!is_error(ret))
+ ret = len;
+ }
}
unlock_iovec(vec, target_vec, count, !send);
unlock_user_struct(msgp, target_msg, send ? 0 : 1);
abi_ulong start;
abi_ulong size;
} shm_regions[N_SHM_REGIONS];
+#endif
struct target_ipc_perm
{
struct target_msqid_ds
{
- struct target_ipc_perm msg_perm;
- abi_ulong msg_stime;
- abi_ulong __unused1;
- abi_ulong msg_rtime;
- abi_ulong __unused2;
- abi_ulong msg_ctime;
- abi_ulong __unused3;
- abi_ulong __msg_cbytes;
- abi_ulong msg_qnum;
- abi_ulong msg_qbytes;
- abi_ulong msg_lspid;
- abi_ulong msg_lrpid;
- abi_ulong __unused4;
- abi_ulong __unused5;
+ struct target_ipc_perm msg_perm;
+ abi_ulong msg_stime;
+#if TARGET_ABI_BITS == 32
+ abi_ulong __unused1;
+#endif
+ abi_ulong msg_rtime;
+#if TARGET_ABI_BITS == 32
+ abi_ulong __unused2;
+#endif
+ abi_ulong msg_ctime;
+#if TARGET_ABI_BITS == 32
+ abi_ulong __unused3;
+#endif
+ abi_ulong __msg_cbytes;
+ abi_ulong msg_qnum;
+ abi_ulong msg_qbytes;
+ abi_ulong msg_lspid;
+ abi_ulong msg_lrpid;
+ abi_ulong __unused4;
+ abi_ulong __unused5;
};
static inline abi_long target_to_host_msqid_ds(struct msqid_ds *host_md,
if (!lock_user_struct(VERIFY_READ, target_md, target_addr, 1))
return -TARGET_EFAULT;
- target_to_host_ipc_perm(&(host_md->msg_perm),target_addr);
+ if (target_to_host_ipc_perm(&(host_md->msg_perm),target_addr))
+ return -TARGET_EFAULT;
host_md->msg_stime = tswapl(target_md->msg_stime);
host_md->msg_rtime = tswapl(target_md->msg_rtime);
host_md->msg_ctime = tswapl(target_md->msg_ctime);
if (!lock_user_struct(VERIFY_WRITE, target_md, target_addr, 0))
return -TARGET_EFAULT;
- host_to_target_ipc_perm(target_addr,&(host_md->msg_perm));
+ if (host_to_target_ipc_perm(target_addr,&(host_md->msg_perm)))
+ return -TARGET_EFAULT;
target_md->msg_stime = tswapl(host_md->msg_stime);
target_md->msg_rtime = tswapl(host_md->msg_rtime);
target_md->msg_ctime = tswapl(host_md->msg_ctime);
return 0;
}
-static inline abi_long do_msgctl(int first, int second, abi_long ptr)
+struct target_msginfo {
+ int msgpool;
+ int msgmap;
+ int msgmax;
+ int msgmnb;
+ int msgmni;
+ int msgssz;
+ int msgtql;
+ unsigned short int msgseg;
+};
+
+static inline abi_long host_to_target_msginfo(abi_ulong target_addr,
+ struct msginfo *host_msginfo)
+{
+ struct target_msginfo *target_msginfo;
+ if (!lock_user_struct(VERIFY_WRITE, target_msginfo, target_addr, 0))
+ return -TARGET_EFAULT;
+ __put_user(host_msginfo->msgpool, &target_msginfo->msgpool);
+ __put_user(host_msginfo->msgmap, &target_msginfo->msgmap);
+ __put_user(host_msginfo->msgmax, &target_msginfo->msgmax);
+ __put_user(host_msginfo->msgmnb, &target_msginfo->msgmnb);
+ __put_user(host_msginfo->msgmni, &target_msginfo->msgmni);
+ __put_user(host_msginfo->msgssz, &target_msginfo->msgssz);
+ __put_user(host_msginfo->msgtql, &target_msginfo->msgtql);
+ __put_user(host_msginfo->msgseg, &target_msginfo->msgseg);
+ unlock_user_struct(target_msginfo, target_addr, 1);
+ return 0;
+}
+
+static inline abi_long do_msgctl(int msgid, int cmd, abi_long ptr)
{
struct msqid_ds dsarg;
- int cmd = second&0xff;
- abi_long ret = 0;
- switch( cmd ) {
+ struct msginfo msginfo;
+ abi_long ret = -TARGET_EINVAL;
+
+ cmd &= 0xff;
+
+ switch (cmd) {
case IPC_STAT:
case IPC_SET:
- target_to_host_msqid_ds(&dsarg,ptr);
- ret = get_errno(msgctl(first, cmd, &dsarg));
- host_to_target_msqid_ds(ptr,&dsarg);
- default:
- ret = get_errno(msgctl(first, cmd, &dsarg));
+ case MSG_STAT:
+ if (target_to_host_msqid_ds(&dsarg,ptr))
+ return -TARGET_EFAULT;
+ ret = get_errno(msgctl(msgid, cmd, &dsarg));
+ if (host_to_target_msqid_ds(ptr,&dsarg))
+ return -TARGET_EFAULT;
+ break;
+ case IPC_RMID:
+ ret = get_errno(msgctl(msgid, cmd, NULL));
+ break;
+ case IPC_INFO:
+ case MSG_INFO:
+ ret = get_errno(msgctl(msgid, cmd, (struct msqid_ds *)&msginfo));
+ if (host_to_target_msginfo(ptr, &msginfo))
+ return -TARGET_EFAULT;
+ break;
}
+
return ret;
}
struct target_msgbuf {
- abi_ulong mtype;
- char mtext[1];
+ abi_long mtype;
+ char mtext[1];
};
static inline abi_long do_msgsnd(int msqid, abi_long msgp,
if (!lock_user_struct(VERIFY_READ, target_mb, msgp, 0))
return -TARGET_EFAULT;
host_mb = malloc(msgsz+sizeof(long));
- host_mb->mtype = tswapl(target_mb->mtype);
- memcpy(host_mb->mtext,target_mb->mtext,msgsz);
+ host_mb->mtype = (abi_long) tswapl(target_mb->mtype);
+ memcpy(host_mb->mtext, target_mb->mtext, msgsz);
ret = get_errno(msgsnd(msqid, host_mb, msgsz, msgflg));
free(host_mb);
unlock_user_struct(target_mb, msgp, 0);
}
static inline abi_long do_msgrcv(int msqid, abi_long msgp,
- unsigned int msgsz, int msgtype,
+ unsigned int msgsz, abi_long msgtyp,
int msgflg)
{
struct target_msgbuf *target_mb;
if (!lock_user_struct(VERIFY_WRITE, target_mb, msgp, 0))
return -TARGET_EFAULT;
+
host_mb = malloc(msgsz+sizeof(long));
- ret = get_errno(msgrcv(msqid, host_mb, msgsz, 1, msgflg));
+ ret = get_errno(msgrcv(msqid, host_mb, msgsz, tswapl(msgtyp), msgflg));
+
if (ret > 0) {
abi_ulong target_mtext_addr = msgp + sizeof(abi_ulong);
target_mtext = lock_user(VERIFY_WRITE, target_mtext_addr, ret, 0);
ret = -TARGET_EFAULT;
goto end;
}
- memcpy(target_mb->mtext, host_mb->mtext, ret);
+ memcpy(target_mb->mtext, host_mb->mtext, ret);
unlock_user(target_mtext, target_mtext_addr, ret);
}
+
target_mb->mtype = tswapl(host_mb->mtype);
free(host_mb);
return ret;
}
+#ifdef TARGET_NR_ipc
/* ??? This only works with linear mappings. */
/* do_ipc() must return target values and target errnos. */
static abi_long do_ipc(unsigned int call, int first,
ret = -TARGET_ENOSYS;
break;
- case IPCOP_msgget:
- ret = get_errno(msgget(first, second));
- break;
+ case IPCOP_msgget:
+ ret = get_errno(msgget(first, second));
+ break;
- case IPCOP_msgsnd:
- ret = do_msgsnd(first, ptr, second, third);
- break;
+ case IPCOP_msgsnd:
+ ret = do_msgsnd(first, ptr, second, third);
+ break;
- case IPCOP_msgctl:
- ret = do_msgctl(first, second, ptr);
- break;
+ case IPCOP_msgctl:
+ ret = do_msgctl(first, second, ptr);
+ break;
- case IPCOP_msgrcv:
- {
- /* XXX: this code is not correct */
- struct ipc_kludge
- {
- void *__unbounded msgp;
- long int msgtyp;
- };
+ case IPCOP_msgrcv:
+ switch (version) {
+ case 0:
+ {
+ struct target_ipc_kludge {
+ abi_long msgp;
+ abi_long msgtyp;
+ } *tmp;
- struct ipc_kludge *foo = (struct ipc_kludge *)g2h(ptr);
- struct msgbuf *msgp = (struct msgbuf *) foo->msgp;
+ if (!lock_user_struct(VERIFY_READ, tmp, ptr, 1)) {
+ ret = -TARGET_EFAULT;
+ break;
+ }
- ret = do_msgrcv(first, (long)msgp, second, 0, third);
+ ret = do_msgrcv(first, tmp->msgp, second, tmp->msgtyp, third);
- }
- break;
+ unlock_user_struct(tmp, ptr, 0);
+ break;
+ }
+ default:
+ ret = do_msgrcv(first, ptr, second, fifth, third);
+ }
+ break;
case IPCOP_shmat:
{
#undef STRUCT
#undef STRUCT_SPECIAL
-#define STRUCT(name, list...) const argtype struct_ ## name ## _def[] = { list, TYPE_NULL };
+#define STRUCT(name, list...) static const argtype struct_ ## name ## _def[] = { list, TYPE_NULL };
#define STRUCT_SPECIAL(name)
#include "syscall_types.h"
#undef STRUCT
#if defined(TARGET_I386)
/* NOTE: there is really one LDT for all the threads */
-uint8_t *ldt_table;
+static uint8_t *ldt_table;
static abi_long read_ldt(abi_ulong ptr, unsigned long bytecount)
{
}
/* allocate the LDT */
if (!ldt_table) {
- ldt_table = malloc(TARGET_LDT_ENTRIES * TARGET_LDT_ENTRY_SIZE);
- if (!ldt_table)
+ env->ldt.base = target_mmap(0,
+ TARGET_LDT_ENTRIES * TARGET_LDT_ENTRY_SIZE,
+ PROT_READ|PROT_WRITE,
+ MAP_ANONYMOUS|MAP_PRIVATE, -1, 0);
+ if (env->ldt.base == -1)
return -TARGET_ENOMEM;
- memset(ldt_table, 0, TARGET_LDT_ENTRIES * TARGET_LDT_ENTRY_SIZE);
- env->ldt.base = h2g((unsigned long)ldt_table);
+ memset(g2h(env->ldt.base), 0,
+ TARGET_LDT_ENTRIES * TARGET_LDT_ENTRY_SIZE);
env->ldt.limit = 0xffff;
+ ldt_table = g2h(env->ldt.base);
}
/* NOTE: same code as Linux kernel */
return -EINVAL;
fork_start();
ret = fork();
-#if defined(USE_NPTL)
- /* There is a race condition here. The parent process could
- theoretically read the TID in the child process before the child
- tid is set. This would require using either ptrace
- (not implemented) or having *_tidptr to point at a shared memory
- mapping. We can't repeat the spinlock hack used above because
- the child process gets its own copy of the lock. */
if (ret == 0) {
+ /* Child Process. */
cpu_clone_regs(env, newsp);
fork_end(1);
- /* Child Process. */
+#if defined(USE_NPTL)
+ /* There is a race condition here. The parent process could
+ theoretically read the TID in the child process before the child
+ tid is set. This would require using either ptrace
+ (not implemented) or having *_tidptr to point at a shared memory
+ mapping. We can't repeat the spinlock hack used above because
+ the child process gets its own copy of the lock. */
if (flags & CLONE_CHILD_SETTID)
put_user_u32(gettid(), child_tidptr);
if (flags & CLONE_PARENT_SETTID)
if (flags & CLONE_SETTLS)
cpu_set_tls (env, newtls);
/* TODO: Implement CLONE_CHILD_CLEARTID. */
+#endif
} else {
fork_end(0);
}
-#else
- if (ret == 0) {
- cpu_clone_regs(env, newsp);
- }
-#endif
}
return ret;
}
#endif
gdb_exit(cpu_env, arg1);
/* XXX: should free thread stack and CPU env */
- _exit(arg1);
+ sys_exit(arg1);
ret = 0; /* avoid warning */
break;
case TARGET_NR_read:
ret = do_ipc(arg1, arg2, arg3, arg4, arg5, arg6);
break;
#endif
+
+#ifdef TARGET_NR_msgctl
+ case TARGET_NR_msgctl:
+ ret = do_msgctl(arg1, arg2, arg3);
+ break;
+#endif
+#ifdef TARGET_NR_msgget
+ case TARGET_NR_msgget:
+ ret = get_errno(msgget(arg1, arg2));
+ break;
+#endif
+#ifdef TARGET_NR_msgrcv
+ case TARGET_NR_msgrcv:
+ ret = do_msgrcv(arg1, arg2, arg3, arg4, arg5);
+ break;
+#endif
+#ifdef TARGET_NR_msgsnd
+ case TARGET_NR_msgsnd:
+ ret = do_msgsnd(arg1, arg2, arg3, arg4);
+ break;
+#endif
case TARGET_NR_fsync:
ret = get_errno(fsync(arg1));
break;
case TARGET_NR_clone:
#if defined(TARGET_SH4)
ret = get_errno(do_fork(cpu_env, arg1, arg2, arg3, arg5, arg4));
+#elif defined(TARGET_CRIS)
+ ret = get_errno(do_fork(cpu_env, arg2, arg1, arg3, arg4, arg5));
#else
ret = get_errno(do_fork(cpu_env, arg1, arg2, arg3, arg4, arg5));
#endif
#ifdef __NR_exit_group
/* new thread calls */
case TARGET_NR_exit_group:
+#ifdef HAVE_GPROF
+ _mcleanup();
+#endif
gdb_exit(cpu_env, arg1);
ret = get_errno(exit_group(arg1));
break;
#elif TARGET_ABI_BITS == 32 && HOST_LONG_BITS == 64
{
struct target_dirent *target_dirp;
- struct dirent *dirp;
+ struct linux_dirent *dirp;
abi_long count = arg3;
dirp = malloc(count);
ret = get_errno(sys_getdents(arg1, dirp, count));
if (!is_error(ret)) {
- struct dirent *de;
+ struct linux_dirent *de;
struct target_dirent *tde;
int len = ret;
int reclen, treclen;
if (tnamelen > 256)
tnamelen = 256;
/* XXX: may not be correct */
- strncpy(tde->d_name, de->d_name, tnamelen);
- de = (struct dirent *)((char *)de + reclen);
+ pstrcpy(tde->d_name, tnamelen, de->d_name);
+ de = (struct linux_dirent *)((char *)de + reclen);
len -= reclen;
tde = (struct target_dirent *)((char *)tde + treclen);
count1 += treclen;
}
#else
{
- struct dirent *dirp;
+ struct linux_dirent *dirp;
abi_long count = arg3;
if (!(dirp = lock_user(VERIFY_WRITE, arg2, count, 0)))
goto efault;
ret = get_errno(sys_getdents(arg1, dirp, count));
if (!is_error(ret)) {
- struct dirent *de;
+ struct linux_dirent *de;
int len = ret;
int reclen;
de = dirp;
de->d_reclen = tswap16(reclen);
tswapls(&de->d_ino);
tswapls(&de->d_off);
- de = (struct dirent *)((char *)de + reclen);
+ de = (struct linux_dirent *)((char *)de + reclen);
len -= reclen;
}
}
#if defined(TARGET_NR_getdents64) && defined(__NR_getdents64)
case TARGET_NR_getdents64:
{
- struct dirent64 *dirp;
+ struct linux_dirent64 *dirp;
abi_long count = arg3;
if (!(dirp = lock_user(VERIFY_WRITE, arg2, count, 0)))
goto efault;
ret = get_errno(sys_getdents64(arg1, dirp, count));
if (!is_error(ret)) {
- struct dirent64 *de;
+ struct linux_dirent64 *de;
int len = ret;
int reclen;
de = dirp;
de->d_reclen = tswap16(reclen);
tswap64s((uint64_t *)&de->d_ino);
tswap64s((uint64_t *)&de->d_off);
- de = (struct dirent64 *)((char *)de + reclen);
+ de = (struct linux_dirent64 *)((char *)de + reclen);
len -= reclen;
}
}
ret = get_errno(getuid());
break;
#endif
+
+#if defined(TARGET_NR_getxuid) && defined(TARGET_ALPHA)
+ /* Alpha specific */
+ case TARGET_NR_getxuid:
+ {
+ uid_t euid;
+ euid=geteuid();
+ ((CPUAlphaState *)cpu_env)->ir[IR_A4]=euid;
+ }
+ ret = get_errno(getuid());
+ break;
+#endif
+#if defined(TARGET_NR_getxgid) && defined(TARGET_ALPHA)
+ /* Alpha specific */
+ case TARGET_NR_getxgid:
+ {
+ uid_t egid;
+ egid=getegid();
+ ((CPUAlphaState *)cpu_env)->ir[IR_A4]=egid;
+ }
+ ret = get_errno(getgid());
+ break;
+#endif
+
#ifdef TARGET_NR_getgid32
case TARGET_NR_getgid32:
ret = get_errno(getgid());
break;
#ifdef TARGET_NR_readahead
case TARGET_NR_readahead:
- goto unimplemented;
+#if TARGET_ABI_BITS == 32
+#ifdef TARGET_ARM
+ if (((CPUARMState *)cpu_env)->eabi)
+ {
+ arg2 = arg3;
+ arg3 = arg4;
+ arg4 = arg5;
+ }
+#endif
+ ret = get_errno(readahead(arg1, ((off64_t)arg3 << 32) | arg2, arg4));
+#else
+ ret = get_errno(readahead(arg1, arg2, arg3));
+#endif
+ break;
#endif
#ifdef TARGET_NR_setxattr
case TARGET_NR_setxattr:
((CPUMIPSState *) cpu_env)->tls_value = arg1;
ret = 0;
break;
+#elif defined(TARGET_CRIS)
+ if (arg1 & 0xff)
+ ret = -TARGET_EINVAL;
+ else {
+ ((CPUCRISState *) cpu_env)->pregs[PR_PID] = arg1;
+ ret = 0;
+ }
+ break;
#elif defined(TARGET_I386) && defined(TARGET_ABI32)
ret = do_set_thread_area(cpu_env, arg1);
break;