📄 syscall.c
字号:
static long do_getsockname(int fd, target_ulong target_addr, target_ulong target_addrlen){ socklen_t addrlen = tget32(target_addrlen); void *addr = alloca(target_addrlen); long ret; ret = get_errno(getsockname(fd, addr, &addrlen)); if (!is_error(ret)) { host_to_target_sockaddr(target_addr, addr, addrlen); tput32(target_addrlen, addrlen); } return ret;}static long do_socketpair(int domain, int type, int protocol, target_ulong target_tab){ int tab[2]; long ret; ret = get_errno(socketpair(domain, type, protocol, tab)); if (!is_error(ret)) { tput32(target_tab, tab[0]); tput32(target_tab + 4, tab[1]); } return ret;}static long do_sendto(int fd, target_ulong msg, size_t len, int flags, target_ulong target_addr, socklen_t addrlen){ void *addr; void *host_msg; long ret; host_msg = lock_user(msg, len, 1); 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)); } else { ret = get_errno(send(fd, host_msg, len, flags)); } unlock_user(host_msg, msg, 0); return ret;}static long do_recvfrom(int fd, target_ulong msg, size_t len, int flags, target_ulong target_addr, target_ulong target_addrlen){ socklen_t addrlen; void *addr; void *host_msg; long ret; host_msg = lock_user(msg, len, 0); if (target_addr) { addrlen = tget32(target_addrlen); addr = alloca(addrlen); ret = get_errno(recvfrom(fd, host_msg, len, flags, addr, &addrlen)); } else { addr = NULL; /* To keep compiler quiet. */ ret = get_errno(recv(fd, host_msg, len, flags)); } if (!is_error(ret)) { if (target_addr) { 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); } return ret;}static long do_socketcall(int num, target_ulong vptr){ long ret; const int n = sizeof(target_ulong); switch(num) { case SOCKOP_socket: { int domain = tgetl(vptr); int type = tgetl(vptr + n); int protocol = tgetl(vptr + 2 * n); ret = do_socket(domain, type, protocol); } break; case SOCKOP_bind: { int sockfd = tgetl(vptr); target_ulong target_addr = tgetl(vptr + n); socklen_t addrlen = tgetl(vptr + 2 * n); ret = do_bind(sockfd, target_addr, addrlen); } break; case SOCKOP_connect: { int sockfd = tgetl(vptr); target_ulong target_addr = tgetl(vptr + n); socklen_t addrlen = tgetl(vptr + 2 * n); ret = do_connect(sockfd, target_addr, addrlen); } break; case SOCKOP_listen: { int sockfd = tgetl(vptr); int backlog = tgetl(vptr + n); ret = get_errno(listen(sockfd, backlog)); } break; case SOCKOP_accept: { int sockfd = tgetl(vptr); target_ulong target_addr = tgetl(vptr + n); target_ulong target_addrlen = tgetl(vptr + 2 * n); ret = do_accept(sockfd, target_addr, target_addrlen); } break; case SOCKOP_getsockname: { int sockfd = tgetl(vptr); target_ulong target_addr = tgetl(vptr + n); target_ulong target_addrlen = tgetl(vptr + 2 * n); ret = do_getsockname(sockfd, target_addr, target_addrlen); } break; case SOCKOP_getpeername: { int sockfd = tgetl(vptr); target_ulong target_addr = tgetl(vptr + n); target_ulong target_addrlen = tgetl(vptr + 2 * n); ret = do_getpeername(sockfd, target_addr, target_addrlen); } break; case SOCKOP_socketpair: { int domain = tgetl(vptr); int type = tgetl(vptr + n); int protocol = tgetl(vptr + 2 * n); target_ulong tab = tgetl(vptr + 3 * n); ret = do_socketpair(domain, type, protocol, tab); } 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); ret = do_sendto(sockfd, msg, len, flags, 0, 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); ret = do_recvfrom(sockfd, msg, len, flags, 0, 0); } 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 addr = tgetl(vptr + 4 * n); socklen_t addrlen = tgetl(vptr + 5 * n); ret = do_sendto(sockfd, msg, len, flags, addr, addrlen); } 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 addr = tgetl(vptr + 4 * n); target_ulong addrlen = tgetl(vptr + 5 * n); ret = do_recvfrom(sockfd, msg, len, flags, addr, addrlen); } 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; int flags; fd = tgetl(vptr); target_msg = tgetl(vptr + n); flags = tgetl(vptr + 2 * n); ret = do_sendrecvmsg(fd, target_msg, flags, (num == SOCKOP_sendmsg)); } 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];union semun { int val; struct senid_ds *buf; unsigned short *array;};/* ??? 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_semop: ret = get_errno(semop(first,(struct sembuf *) ptr, second)); break; case IPCOP_semget: ret = get_errno(semget(first, second, third)); break; case IPCOP_semctl: ret = get_errno(semctl(first, second, third, ((union semun*)ptr)->val)); break; case IPCOP_semtimedop: gemu_log("Unsupported ipc call: %ld (version %d)\n", call, version); ret = -ENOSYS; break; case IPCOP_msgget: ret = get_errno(msgget(first, second)); break; case IPCOP_msgsnd: ret = get_errno(msgsnd(first, (struct msgbuf *) ptr, second, third)); break; case IPCOP_msgctl: ret = get_errno(msgctl(first, second, (struct msqid_ds *) ptr)); break; case IPCOP_msgrcv: { struct ipc_kludge { void *__unbounded msgp; long int msgtyp; }; struct ipc_kludge *foo = (struct ipc_kludge *) ptr; struct msgbuf *msgp = (struct msgbuf *) foo->msgp; ret = get_errno(msgrcv(first, msgp, second, 0, third)); } break; 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++;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -