📄 syscall.c
字号:
/* * Linux syscalls * * Copyright (c) 2003 Fabrice Bellard * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * 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. */#include <stdlib.h>#include <stdio.h>#include <stdarg.h>#include <string.h>#include <elf.h>#include <endian.h>#include <errno.h>#include <unistd.h>#include <fcntl.h>#include <time.h>#include <sys/types.h>#include <sys/wait.h>#include <sys/time.h>#include <sys/stat.h>#include <sys/mount.h>#include <sys/resource.h>#include <sys/mman.h>#include <sys/swap.h>#include <signal.h>#include <sched.h>#include <sys/socket.h>#include <sys/uio.h>#include <sys/poll.h>#include <sys/times.h>#include <sys/shm.h>#include <sys/sem.h>#include <sys/statfs.h>#include <utime.h>#include <sys/sysinfo.h>//#include <sys/user.h>#include <netinet/ip.h>#include <netinet/tcp.h>#define termios host_termios#define winsize host_winsize#define termio host_termio#define sgttyb host_sgttyb /* same as target */#define tchars host_tchars /* same as target */#define ltchars host_ltchars /* same as target */#include <linux/termios.h>#include <linux/unistd.h>#include <linux/utsname.h>#include <linux/cdrom.h>#include <linux/hdreg.h>#include <linux/soundcard.h>#include <linux/dirent.h>#include <linux/kd.h>#include "qemu.h"//#define DEBUG#if defined(TARGET_I386) || defined(TARGET_ARM) || defined(TARGET_SPARC) \ || defined(TARGET_M68K)/* 16 bit uid wrappers emulation */#define USE_UID16#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])#undef _syscall0#undef _syscall1#undef _syscall2#undef _syscall3#undef _syscall4#undef _syscall5#undef _syscall6#define _syscall0(type,name) \type name (void) \{ \ return syscall(__NR_##name); \}#define _syscall1(type,name,type1,arg1) \type name (type1 arg1) \{ \ return syscall(__NR_##name, arg1); \}#define _syscall2(type,name,type1,arg1,type2,arg2) \type name (type1 arg1,type2 arg2) \{ \ return syscall(__NR_##name, arg1, arg2); \}#define _syscall3(type,name,type1,arg1,type2,arg2,type3,arg3) \type name (type1 arg1,type2 arg2,type3 arg3) \{ \ return syscall(__NR_##name, arg1, arg2, arg3); \}#define _syscall4(type,name,type1,arg1,type2,arg2,type3,arg3,type4,arg4) \type name (type1 arg1,type2 arg2,type3 arg3,type4 arg4) \{ \ return syscall(__NR_##name, arg1, arg2, arg3, arg4); \}#define _syscall5(type,name,type1,arg1,type2,arg2,type3,arg3,type4,arg4, \ type5,arg5) \type name (type1 arg1,type2 arg2,type3 arg3,type4 arg4,type5 arg5) \{ \ return syscall(__NR_##name, arg1, arg2, arg3, arg4, arg5); \}#define _syscall6(type,name,type1,arg1,type2,arg2,type3,arg3,type4,arg4, \ type5,arg5,type6,arg6) \type name (type1 arg1,type2 arg2,type3 arg3,type4 arg4,type5 arg5,type6 arg6) \{ \ return syscall(__NR_##name, arg1, arg2, arg3, arg4, arg5, arg6); \}#define __NR_sys_uname __NR_uname#define __NR_sys_getcwd1 __NR_getcwd#define __NR_sys_getdents __NR_getdents#define __NR_sys_getdents64 __NR_getdents64#define __NR_sys_rt_sigqueueinfo __NR_rt_sigqueueinfo#if defined(__alpha__) || defined (__ia64__) || defined(__x86_64__)#define __NR__llseek __NR_lseek#endif#ifdef __NR_gettid_syscall0(int, gettid)#elsestatic int gettid(void) { return -ENOSYS;}#endif_syscall1(int,sys_uname,struct new_utsname *,buf)_syscall2(int,sys_getcwd1,char *,buf,size_t,size)_syscall3(int, sys_getdents, uint, fd, struct dirent *, dirp, uint, count);_syscall3(int, sys_getdents64, uint, fd, struct dirent64 *, dirp, uint, count);_syscall5(int, _llseek, uint, fd, ulong, hi, ulong, lo, loff_t *, res, uint, wh);_syscall3(int,sys_rt_sigqueueinfo,int,pid,int,sig,siginfo_t *,uinfo)#ifdef __NR_exit_group_syscall1(int,exit_group,int,error_code)#endifextern int personality(int);extern int flock(int, int);extern int setfsuid(int);extern int setfsgid(int);extern int setresuid(uid_t, uid_t, uid_t);extern int getresuid(uid_t *, uid_t *, uid_t *);extern int setresgid(gid_t, gid_t, gid_t);extern int getresgid(gid_t *, gid_t *, gid_t *);extern int setgroups(int, gid_t *);static inline long get_errno(long ret){ if (ret == -1) return -errno; else return ret;}static inline int is_error(long ret){ return (unsigned long)ret >= (unsigned long)(-4096);}static target_ulong target_brk;static target_ulong target_original_brk;void target_set_brk(target_ulong new_brk){ target_original_brk = target_brk = new_brk;}long do_brk(target_ulong new_brk){ target_ulong brk_page; long mapped_addr; int new_alloc_size; if (!new_brk) return target_brk; if (new_brk < target_original_brk) return -ENOMEM; brk_page = HOST_PAGE_ALIGN(target_brk); /* If the new brk is less than this, set it and we're done... */ if (new_brk < brk_page) { target_brk = new_brk; return target_brk; } /* We need to allocate more memory after the brk... */ new_alloc_size = HOST_PAGE_ALIGN(new_brk - brk_page + 1); mapped_addr = get_errno(target_mmap(brk_page, new_alloc_size, PROT_READ|PROT_WRITE, MAP_ANON|MAP_FIXED|MAP_PRIVATE, 0, 0)); if (is_error(mapped_addr)) { return mapped_addr; } else { target_brk = new_brk; return target_brk; }}static inline fd_set *target_to_host_fds(fd_set *fds, target_long *target_fds, int n){#if !defined(BSWAP_NEEDED) && !defined(WORDS_BIGENDIAN) return (fd_set *)target_fds;#else int i, b; if (target_fds) { FD_ZERO(fds); for(i = 0;i < n; i++) { b = (tswapl(target_fds[i / TARGET_LONG_BITS]) >> (i & (TARGET_LONG_BITS - 1))) & 1; if (b) FD_SET(i, fds); } return fds; } else { return NULL; }#endif}static inline void host_to_target_fds(target_long *target_fds, fd_set *fds, int n){#if !defined(BSWAP_NEEDED) && !defined(WORDS_BIGENDIAN) /* nothing to do */#else int i, nw, j, k; target_long v; if (target_fds) { nw = (n + TARGET_LONG_BITS - 1) / TARGET_LONG_BITS; k = 0; for(i = 0;i < nw; i++) { v = 0; for(j = 0; j < TARGET_LONG_BITS; j++) { v |= ((FD_ISSET(k, fds) != 0) << j); k++; } target_fds[i] = tswapl(v); } }#endif}#if defined(__alpha__)#define HOST_HZ 1024#else#define HOST_HZ 100#endifstatic inline long host_to_target_clock_t(long ticks){#if HOST_HZ == TARGET_HZ return ticks;#else return ((int64_t)ticks * TARGET_HZ) / HOST_HZ;#endif}static inline void host_to_target_rusage(target_ulong target_addr, const struct rusage *rusage){ struct target_rusage *target_rusage; lock_user_struct(target_rusage, target_addr, 0); target_rusage->ru_utime.tv_sec = tswapl(rusage->ru_utime.tv_sec); target_rusage->ru_utime.tv_usec = tswapl(rusage->ru_utime.tv_usec); target_rusage->ru_stime.tv_sec = tswapl(rusage->ru_stime.tv_sec); target_rusage->ru_stime.tv_usec = tswapl(rusage->ru_stime.tv_usec); target_rusage->ru_maxrss = tswapl(rusage->ru_maxrss); target_rusage->ru_ixrss = tswapl(rusage->ru_ixrss); target_rusage->ru_idrss = tswapl(rusage->ru_idrss); target_rusage->ru_isrss = tswapl(rusage->ru_isrss); target_rusage->ru_minflt = tswapl(rusage->ru_minflt); target_rusage->ru_majflt = tswapl(rusage->ru_majflt); target_rusage->ru_nswap = tswapl(rusage->ru_nswap); target_rusage->ru_inblock = tswapl(rusage->ru_inblock); target_rusage->ru_oublock = tswapl(rusage->ru_oublock); target_rusage->ru_msgsnd = tswapl(rusage->ru_msgsnd); target_rusage->ru_msgrcv = tswapl(rusage->ru_msgrcv); target_rusage->ru_nsignals = tswapl(rusage->ru_nsignals); target_rusage->ru_nvcsw = tswapl(rusage->ru_nvcsw); target_rusage->ru_nivcsw = tswapl(rusage->ru_nivcsw); unlock_user_struct(target_rusage, target_addr, 1);}static inline void target_to_host_timeval(struct timeval *tv, target_ulong target_addr){ struct target_timeval *target_tv; lock_user_struct(target_tv, target_addr, 1); tv->tv_sec = tswapl(target_tv->tv_sec); tv->tv_usec = tswapl(target_tv->tv_usec); unlock_user_struct(target_tv, target_addr, 0);}static inline void host_to_target_timeval(target_ulong target_addr, const struct timeval *tv){ struct target_timeval *target_tv; lock_user_struct(target_tv, target_addr, 0); target_tv->tv_sec = tswapl(tv->tv_sec); target_tv->tv_usec = tswapl(tv->tv_usec); unlock_user_struct(target_tv, target_addr, 1);}static long do_select(long n, target_ulong rfd_p, target_ulong wfd_p, target_ulong efd_p, target_ulong target_tv){ fd_set rfds, wfds, efds; fd_set *rfds_ptr, *wfds_ptr, *efds_ptr; target_long *target_rfds, *target_wfds, *target_efds; struct timeval tv, *tv_ptr; long ret; int ok; if (rfd_p) { target_rfds = lock_user(rfd_p, sizeof(target_long) * n, 1); rfds_ptr = target_to_host_fds(&rfds, target_rfds, n); } else { target_rfds = NULL; rfds_ptr = NULL; } if (wfd_p) { target_wfds = lock_user(wfd_p, sizeof(target_long) * n, 1); wfds_ptr = target_to_host_fds(&wfds, target_wfds, n); } else { target_wfds = NULL; wfds_ptr = NULL; } if (efd_p) { target_efds = lock_user(efd_p, sizeof(target_long) * n, 1); efds_ptr = target_to_host_fds(&efds, target_efds, n); } else { target_efds = NULL; efds_ptr = NULL; } if (target_tv) { target_to_host_timeval(&tv, target_tv); tv_ptr = &tv; } else { tv_ptr = NULL; } ret = get_errno(select(n, rfds_ptr, wfds_ptr, efds_ptr, tv_ptr)); ok = !is_error(ret); if (ok) { host_to_target_fds(target_rfds, rfds_ptr, n); host_to_target_fds(target_wfds, wfds_ptr, n); host_to_target_fds(target_efds, efds_ptr, n); if (target_tv) { host_to_target_timeval(target_tv, &tv); } } if (target_rfds) unlock_user(target_rfds, rfd_p, ok ? sizeof(target_long) * n : 0); if (target_wfds) unlock_user(target_wfds, wfd_p, ok ? sizeof(target_long) * n : 0); if (target_efds) unlock_user(target_efds, efd_p, ok ? sizeof(target_long) * n : 0); return ret;}static inline void target_to_host_sockaddr(struct sockaddr *addr, target_ulong target_addr, socklen_t len){ struct target_sockaddr *target_saddr; target_saddr = lock_user(target_addr, len, 1); memcpy(addr, target_saddr, len); addr->sa_family = tswap16(target_saddr->sa_family); unlock_user(target_saddr, target_addr, 0);}static inline void host_to_target_sockaddr(target_ulong target_addr, struct sockaddr *addr, socklen_t len){ struct target_sockaddr *target_saddr; target_saddr = lock_user(target_addr, len, 0); memcpy(target_saddr, addr, len); target_saddr->sa_family = tswap16(addr->sa_family); unlock_user(target_saddr, target_addr, len);}/* ??? Should this also swap msgh->name? */static inline void target_to_host_cmsg(struct msghdr *msgh, struct target_msghdr *target_msgh){ struct cmsghdr *cmsg = CMSG_FIRSTHDR(msgh); struct target_cmsghdr *target_cmsg = TARGET_CMSG_FIRSTHDR(target_msgh); socklen_t space = 0; while (cmsg && target_cmsg) { void *data = CMSG_DATA(cmsg); void *target_data = TARGET_CMSG_DATA(target_cmsg);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -