📄 syscall.c
字号:
socklen_t addrlen = tget32(target_addrlen); void *addr = alloca(addrlen); ret = get_errno(getsockname(sockfd, addr, &addrlen)); if (!is_error(ret)) { host_to_target_sockaddr(target_addr, addr, addrlen); tput32(target_addrlen, addrlen); } } break; case SOCKOP_getpeername: { int sockfd = tgetl(vptr); target_ulong target_addr = tgetl(vptr + n); target_ulong target_addrlen = tgetl(vptr + 2 * n); socklen_t addrlen = tget32(target_addrlen); void *addr = alloca(addrlen); ret = get_errno(getpeername(sockfd, addr, &addrlen)); if (!is_error(ret)) { host_to_target_sockaddr(target_addr, addr, addrlen); tput32(target_addrlen, addrlen); } } break; case SOCKOP_socketpair: { int domain = tgetl(vptr); int type = tgetl(vptr + n); int protocol = tgetl(vptr + 2 * n); target_ulong target_tab = tgetl(vptr + 3 * n); int tab[2]; ret = get_errno(socketpair(domain, type, protocol, tab)); if (!is_error(ret)) { tput32(target_tab, tab[0]); tput32(target_tab + 4, tab[1]); } } break; case SOCKOP_send: { int sockfd = tgetl(vptr); target_ulong msg = tgetl(vptr + n); size_t len = tgetl(vptr + 2 * n); int flags = tgetl(vptr + 3 * n); void *host_msg; host_msg = lock_user(msg, len, 1); ret = get_errno(send(sockfd, host_msg, len, flags)); unlock_user(host_msg, msg, 0); } break; case SOCKOP_recv: { int sockfd = tgetl(vptr); target_ulong msg = tgetl(vptr + n); size_t len = tgetl(vptr + 2 * n); int flags = tgetl(vptr + 3 * n); void *host_msg; host_msg = lock_user(msg, len, 0); ret = get_errno(recv(sockfd, host_msg, len, flags)); unlock_user(host_msg, msg, ret); } break; case SOCKOP_sendto: { int sockfd = tgetl(vptr); target_ulong msg = tgetl(vptr + n); size_t len = tgetl(vptr + 2 * n); int flags = tgetl(vptr + 3 * n); target_ulong target_addr = tgetl(vptr + 4 * n); socklen_t addrlen = tgetl(vptr + 5 * n); void *addr = alloca(addrlen); void *host_msg; host_msg = lock_user(msg, len, 1); target_to_host_sockaddr(addr, target_addr, addrlen); ret = get_errno(sendto(sockfd, host_msg, len, flags, addr, addrlen)); unlock_user(host_msg, msg, 0); } break; case SOCKOP_recvfrom: { int sockfd = tgetl(vptr); target_ulong msg = tgetl(vptr + n); size_t len = tgetl(vptr + 2 * n); int flags = tgetl(vptr + 3 * n); target_ulong target_addr = tgetl(vptr + 4 * n); target_ulong target_addrlen = tgetl(vptr + 5 * n); socklen_t addrlen = tget32(target_addrlen); void *addr = alloca(addrlen); void *host_msg; host_msg = lock_user(msg, len, 0); ret = get_errno(recvfrom(sockfd, host_msg, len, flags, addr, &addrlen)); if (!is_error(ret)) { host_to_target_sockaddr(target_addr, addr, addrlen); tput32(target_addrlen, addrlen); unlock_user(host_msg, msg, len); } else { unlock_user(host_msg, msg, 0); } } break; case SOCKOP_shutdown: { int sockfd = tgetl(vptr); int how = tgetl(vptr + n); ret = get_errno(shutdown(sockfd, how)); } break; case SOCKOP_sendmsg: case SOCKOP_recvmsg: { int fd; target_ulong target_msg; struct target_msghdr *msgp; struct msghdr msg; int flags, count; struct iovec *vec; target_ulong target_vec; int send = (num == SOCKOP_sendmsg); target_msg = tgetl(vptr + n); lock_user_struct(msgp, target_msg, 1); 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); } else { msg.msg_name = NULL; msg.msg_namelen = 0; } msg.msg_controllen = 2 * tswapl(msgp->msg_controllen); msg.msg_control = alloca(msg.msg_controllen); msg.msg_flags = tswap32(msgp->msg_flags); count = tswapl(msgp->msg_iovlen); vec = alloca(count * sizeof(struct iovec)); target_vec = tswapl(msgp->msg_iov); lock_iovec(vec, target_vec, count, send); msg.msg_iovlen = count; msg.msg_iov = vec; fd = tgetl(vptr); flags = tgetl(vptr + 2 * n); if (send) { target_to_host_cmsg(&msg, msgp); ret = get_errno(sendmsg(fd, &msg, flags)); } else { ret = get_errno(recvmsg(fd, &msg, flags)); if (!is_error(ret)) host_to_target_cmsg(msgp, &msg); } unlock_iovec(vec, target_vec, count, !send); } break; case SOCKOP_setsockopt: { int sockfd = tgetl(vptr); int level = tgetl(vptr + n); int optname = tgetl(vptr + 2 * n); target_ulong optval = tgetl(vptr + 3 * n); socklen_t optlen = tgetl(vptr + 4 * n); ret = do_setsockopt(sockfd, level, optname, optval, optlen); } break; case SOCKOP_getsockopt: { int sockfd = tgetl(vptr); int level = tgetl(vptr + n); int optname = tgetl(vptr + 2 * n); target_ulong optval = tgetl(vptr + 3 * n); target_ulong poptlen = tgetl(vptr + 4 * n); ret = do_getsockopt(sockfd, level, optname, optval, poptlen); } break; default: gemu_log("Unsupported socketcall: %d\n", num); ret = -ENOSYS; break; } return ret;}#define N_SHM_REGIONS 32static struct shm_region { uint32_t start; uint32_t size;} shm_regions[N_SHM_REGIONS];/* ??? This only works with linear mappings. */static long do_ipc(long call, long first, long second, long third, long ptr, long fifth){ int version; long ret = 0; unsigned long raddr; struct shmid_ds shm_info; int i; version = call >> 16; call &= 0xffff; switch (call) { case IPCOP_shmat: /* SHM_* flags are the same on all linux platforms */ ret = get_errno((long) shmat(first, (void *) ptr, second)); if (is_error(ret)) break; raddr = ret; /* 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((void *) raddr); 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(raddr, (uint32_t *)third)) return -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 *) 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: %ld (version %d)\n", call, version); ret = -ENOSYS; break; } return ret;}/* 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. */static long do_ioctl(long fd, long cmd, long arg){ const IOCTLEntry *ie; const argtype *arg_type; 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", cmd); return -ENOSYS; } if (ie->target_cmd == cmd) break; ie++; } arg_type = ie->arg_type;#if defined(DEBUG) gemu_log("ioctl: cmd=0x%04lx (%s)\n", 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(arg, target_size, 0); thunk_convert(argptr, buf_temp, arg_type, THUNK_TARGET); unlock_user(argptr, arg, target_size); } break; case IOC_W: argptr = lock_user(arg, target_size, 1); 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(arg, target_size, 1); thunk_convert(buf_temp, argptr, arg_type, THUNK_HOST); unlock_user(argptr, arg, 0); ret = get_errno(ioctl(fd, ie->host_cmd, buf_temp)); if (!is_error(ret)) { argptr = lock_user(arg, target_size, 0); thunk_convert(argptr, buf_temp, arg_type, THUNK_TARGET); unlock_user(argptr, arg, target_size); } break; } break; default: gemu_log("Unsupported ioctl type: cmd=0x%04lx type=%d\n", cmd, arg_type[0]); ret = -ENOSYS; break; } return ret;}bitmask_transtbl iflag_tbl[] = { { TARGET_IGNBRK, TARGET_IGNBRK, IGNBRK, IGNBRK }, { TARGET_BRKINT, TARGET_BRKINT, BRKINT, BRKINT }, { TARGET_IGNPAR, TARGET_IGNPAR, IGNPAR, IGNPAR }, { TARGET_PARMRK, TARGET_PARMRK, PARMRK, PARMRK }, { TARGET_INPCK, TARGET_INPCK, INPCK, INPCK }, { TARGET_ISTRIP, TARGET_ISTRIP, ISTRIP, ISTRIP }, { TARGET_INLCR, TARGET_INLCR, INLCR, INLCR }, { TARGET_IGNCR, TARGET_IGNCR, IGNCR, IGNCR }, { TARGET_ICRNL, TARGET_ICRNL, ICRNL, ICRNL }, { TARGET_IUCLC, TARGET_IUCLC, IUCLC, IUCLC }, { TARGET_IXON, TARGET_IXON, IXON, IXON }, { TARGET_IXANY, TARGET_IXANY, IXANY, IXANY }, { TARGET_IXOFF, TARGET_IXOFF, IXOFF, IXOFF }, { TARGET_IMAXBEL, TARGET_IMAXBEL, IMAXBEL, IMAXBEL }, { 0, 0, 0, 0 }};bitmask_transtbl oflag_tbl[] = { { TARGET_OPOST, TARGET_OPOST, OPOST, OPOST }, { TARGET_OLCUC, TARGET_OLCUC, OLCUC, OLCUC }, { TARGET_ONLCR, TARGET_ONLCR, ONLCR, ONLCR }, { TARGET_OCRNL, TARGET_OCRNL, OCRNL, OCRNL }, { TARGET_ONOCR, TARGET_ONOCR, ONOCR, ONOCR }, { TARGET_ONLRET, TARGET_ONLRET, ONLRET, ONLRET }, { TARGET_OFILL, TARGET_OFILL, OFILL, OFILL }, { TARGET_OFDEL, TARGET_OFDEL, OFDEL, OFDEL }, { TARGET_NLDLY, TARGET_NL0, NLDLY, NL0 }, { TARGET_NLDLY, TARGET_NL1, NLDLY, NL1 }, { TARGET_CRDLY, TARGET_CR0, CRDLY, CR0 }, { TARGET_CRDLY, TARGET_CR1, CRDLY, CR1 }, { TARGET_CRDLY, TARGET_CR2, CRDLY, CR2 }, { TARGET_CRDLY, TARGET_CR3, CRDLY, CR3 },
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -