📄 syscall.c.svn-base
字号:
case SETVAL: if (lock_user_struct(VERIFY_WRITE, target_su, target_addr, 0)) return -TARGET_EFAULT; target_su->val = tswapl(host_su->val); unlock_user_struct(target_su, target_addr, 1); break; case GETALL: case SETALL: if (lock_user_struct(VERIFY_WRITE, target_su, target_addr, 0)) return -TARGET_EFAULT; *target_su->array = tswap16(*host_su->array); unlock_user_struct(target_su, target_addr, 1); break; default: gemu_log("semun operation not fully supported: %d\n", (int)cmd); } return 0;}static inline abi_long do_semctl(int first, int second, int third, abi_long ptr){ union semun arg; struct semid_ds dsarg; int cmd = third&0xff; abi_long ret = 0; switch( cmd ) { case GETVAL: target_to_host_semun(cmd,&arg,ptr,&dsarg); ret = get_errno(semctl(first, second, cmd, arg)); host_to_target_semun(cmd,ptr,&arg,&dsarg); break; case SETVAL: target_to_host_semun(cmd,&arg,ptr,&dsarg); ret = get_errno(semctl(first, second, cmd, arg)); host_to_target_semun(cmd,ptr,&arg,&dsarg); break; case GETALL: target_to_host_semun(cmd,&arg,ptr,&dsarg); ret = get_errno(semctl(first, second, cmd, arg)); host_to_target_semun(cmd,ptr,&arg,&dsarg); break; case SETALL: target_to_host_semun(cmd,&arg,ptr,&dsarg); ret = get_errno(semctl(first, second, cmd, arg)); host_to_target_semun(cmd,ptr,&arg,&dsarg); break; case IPC_STAT: target_to_host_semun(cmd,&arg,ptr,&dsarg); ret = get_errno(semctl(first, second, cmd, arg)); host_to_target_semun(cmd,ptr,&arg,&dsarg); break; case IPC_SET: target_to_host_semun(cmd,&arg,ptr,&dsarg); ret = get_errno(semctl(first, second, cmd, arg)); host_to_target_semun(cmd,ptr,&arg,&dsarg); break; default: ret = get_errno(semctl(first, second, cmd, arg)); } return ret;}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;};static inline abi_long target_to_host_msqid_ds(struct msqid_ds *host_md, abi_ulong target_addr){ struct target_msqid_ds *target_md; if (!lock_user_struct(VERIFY_READ, target_md, target_addr, 1)) return -TARGET_EFAULT; target_to_host_ipc_perm(&(host_md->msg_perm),target_addr); 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); host_md->__msg_cbytes = tswapl(target_md->__msg_cbytes); host_md->msg_qnum = tswapl(target_md->msg_qnum); host_md->msg_qbytes = tswapl(target_md->msg_qbytes); host_md->msg_lspid = tswapl(target_md->msg_lspid); host_md->msg_lrpid = tswapl(target_md->msg_lrpid); unlock_user_struct(target_md, target_addr, 0); return 0;}static inline abi_long host_to_target_msqid_ds(abi_ulong target_addr, struct msqid_ds *host_md){ struct target_msqid_ds *target_md; if (!lock_user_struct(VERIFY_WRITE, target_md, target_addr, 0)) return -TARGET_EFAULT; host_to_target_ipc_perm(target_addr,&(host_md->msg_perm)); 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); target_md->__msg_cbytes = tswapl(host_md->__msg_cbytes); target_md->msg_qnum = tswapl(host_md->msg_qnum); target_md->msg_qbytes = tswapl(host_md->msg_qbytes); target_md->msg_lspid = tswapl(host_md->msg_lspid); target_md->msg_lrpid = tswapl(host_md->msg_lrpid); unlock_user_struct(target_md, target_addr, 1); return 0;}static inline abi_long do_msgctl(int first, int second, abi_long ptr){ struct msqid_ds dsarg; int cmd = second&0xff; abi_long ret = 0; 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)); } return ret;}struct target_msgbuf { abi_ulong mtype; char mtext[1];};static inline abi_long do_msgsnd(int msqid, abi_long msgp, unsigned int msgsz, int msgflg){ struct target_msgbuf *target_mb; struct msgbuf *host_mb; abi_long ret = 0; if (!lock_user_struct(VERIFY_READ, target_mb, msgp, 0)) return -TARGET_EFAULT; host_mb = malloc(msgsz+sizeof(long)); host_mb->mtype = 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); return ret;}static inline abi_long do_msgrcv(int msqid, abi_long msgp, unsigned int msgsz, int msgtype, int msgflg){ struct target_msgbuf *target_mb; char *target_mtext; struct msgbuf *host_mb; abi_long ret = 0; 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)); if (ret > 0) { abi_ulong target_mtext_addr = msgp + sizeof(abi_ulong); target_mtext = lock_user(VERIFY_WRITE, target_mtext_addr, ret, 0); if (!target_mtext) { ret = -TARGET_EFAULT; goto end; } memcpy(target_mb->mtext, host_mb->mtext, ret); unlock_user(target_mtext, target_mtext_addr, ret); } target_mb->mtype = tswapl(host_mb->mtype); free(host_mb);end: if (target_mb) unlock_user_struct(target_mb, msgp, 1); return ret;}/* ??? 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, int second, int third, abi_long ptr, abi_long fifth){ int version; abi_long ret = 0; struct shmid_ds shm_info; int i; version = call >> 16; call &= 0xffff; switch (call) { case IPCOP_semop: ret = get_errno(semop(first,(struct sembuf *)g2h(ptr), second)); break; case IPCOP_semget: ret = get_errno(semget(first, second, third)); break; case IPCOP_semctl: ret = do_semctl(first, second, third, ptr); break; case IPCOP_semtimedop: gemu_log("Unsupported ipc call: %d (version %d)\n", call, version); ret = -TARGET_ENOSYS; break; case IPCOP_msgget: ret = get_errno(msgget(first, second)); break; case IPCOP_msgsnd: ret = do_msgsnd(first, ptr, second, third); 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; }; struct ipc_kludge *foo = (struct ipc_kludge *)g2h(ptr); struct msgbuf *msgp = (struct msgbuf *) foo->msgp; ret = do_msgrcv(first, (long)msgp, second, 0, third); } break; case IPCOP_shmat: { abi_ulong raddr; void *host_addr; /* SHM_* flags are the same on all linux platforms */ host_addr = shmat(first, (void *)g2h(ptr), second); if (host_addr == (void *)-1) { ret = get_errno((long)host_addr); break; } raddr = h2g((unsigned long)host_addr); /* find out the length of the shared memory segment */ ret = get_errno(shmctl(first, IPC_STAT, &shm_info)); if (is_error(ret)) { /* can't get length, bail out */ shmdt(host_addr); break; } page_set_flags(raddr, raddr + shm_info.shm_segsz, PAGE_VALID | PAGE_READ | ((second & SHM_RDONLY)? 0: PAGE_WRITE)); for (i = 0; i < N_SHM_REGIONS; ++i) { if (shm_regions[i].start == 0) { shm_regions[i].start = raddr; shm_regions[i].size = shm_info.shm_segsz; break; } } if (put_user_ual(raddr, third)) return -TARGET_EFAULT; ret = 0; } break; case IPCOP_shmdt: for (i = 0; i < N_SHM_REGIONS; ++i) { if (shm_regions[i].start == ptr) { shm_regions[i].start = 0; page_set_flags(ptr, shm_regions[i].size, 0); break; } } ret = get_errno(shmdt((void *)g2h(ptr))); break; case IPCOP_shmget: /* IPC_* flag values are the same on all linux platforms */ ret = get_errno(shmget(first, second, third)); break; /* IPC_* and SHM_* command values are the same on all linux platforms */ case IPCOP_shmctl: switch(second) { case IPC_RMID: case SHM_LOCK: case SHM_UNLOCK: ret = get_errno(shmctl(first, second, NULL)); break; default: goto unimplemented; } break; default: unimplemented: gemu_log("Unsupported ipc call: %d (version %d)\n", call, version); ret = -TARGET_ENOSYS; break; } return ret;}#endif/* kernel structure types definitions */#define IFNAMSIZ 16#define STRUCT(name, list...) STRUCT_ ## name,#define STRUCT_SPECIAL(name) STRUCT_ ## name,enum {#include "syscall_types.h"};#undef STRUCT#undef STRUCT_SPECIAL#define STRUCT(name, list...) const argtype struct_ ## name ## _def[] = { list, TYPE_NULL };#define STRUCT_SPECIAL(name)#include "syscall_types.h"#undef STRUCT#undef STRUCT_SPECIALtypedef struct IOCTLEntry { unsigned int target_cmd; unsigned int host_cmd; const char *name; int access; const argtype arg_type[5];} IOCTLEntry;#define IOC_R 0x0001#define IOC_W 0x0002#define IOC_RW (IOC_R | IOC_W)#define MAX_STRUCT_SIZE 4096IOCTLEntry ioctl_entries[] = {#define IOCTL(cmd, access, types...) \ { TARGET_ ## cmd, cmd, #cmd, access, { types } },#include "ioctls.h" { 0, 0, },};/* ??? Implement proper locking for ioctls. *//* do_ioctl() Must return target values and target errnos. */static abi_long do_ioctl(int fd, abi_long cmd, abi_long arg){ const IOCTLEntry *ie; const argtype *arg_type; abi_long ret; uint8_t buf_temp[MAX_STRUCT_SIZE]; int target_size; void *argptr; ie = ioctl_entries; for(;;) { if (ie->target_cmd == 0) { gemu_log("Unsupported ioctl: cmd=0x%04lx\n", (long)cmd); return -TARGET_ENOSYS; } if (ie->target_cmd == cmd) break; ie++; } arg_type = ie->arg_type;#if defined(DEBUG) gemu_log("ioctl: cmd=0x%04lx (%s)\n", (long)cmd, ie->name);#endif switch(arg_type[0]) { case TYPE_NULL: /* no argument */ ret = get_errno(ioctl(fd, ie->host_cmd)); break; case TYPE_PTRVOID: case TYPE_INT: /* int argment */ ret = get_errno(ioctl(fd, ie->host_cmd, arg)); break; case TYPE_PTR: arg_type++; target_size = thunk_type_size(arg_type, 0); switch(ie->access) { case IOC_R: ret = get_errno(ioctl(fd, ie->host_cmd, buf_temp)); if (!is_error(ret)) { argptr = lock_user(VERIFY_WRITE, arg, target_size, 0); if (!argptr) return -TARGET_EFAULT; thunk_convert(argptr, buf_temp, arg_type, THUNK_TARGET); unlock_user(argptr, arg, target_size); } break; case IOC_W: argptr = lock_user(VERIFY_READ, arg, target_size, 1); if (!argptr) return -TARGET_EFAULT; thunk_convert(buf_temp, argptr, arg_type, THUNK_HOST); unlock_user(argptr, arg, 0); ret = get_errno(ioctl(fd, ie->host_cmd, buf_temp)); break; default: case IOC_RW: argptr = lock_user(VERIFY_READ, arg, target_size, 1); if (!argptr) return -TARGET_EFAULT;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -