⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 syscall.c

📁 qemu性能直逼VMware的仿真器QEMU 的模擬速度約為實機的 25%;約為 Bochs 的 60 倍。Plex86、User-Mode-Linux、VMware 和 Virtual PC 則比
💻 C
📖 第 1 页 / 共 5 页
字号:
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 + -