📄 syscall.c
字号:
ret = fcntl(fd, cmd, arg); break; } return ret;}#ifdef USE_UID16static inline int high2lowuid(int uid){ if (uid > 65535) return 65534; else return uid;}static inline int high2lowgid(int gid){ if (gid > 65535) return 65534; else return gid;}static inline int low2highuid(int uid){ if ((int16_t)uid == -1) return -1; else return uid;}static inline int low2highgid(int gid){ if ((int16_t)gid == -1) return -1; else return gid;}#endif /* USE_UID16 */void syscall_init(void){ IOCTLEntry *ie; const argtype *arg_type; int size;#define STRUCT(name, list...) thunk_register_struct(STRUCT_ ## name, #name, struct_ ## name ## _def); #define STRUCT_SPECIAL(name) thunk_register_struct_direct(STRUCT_ ## name, #name, &struct_ ## name ## _def); #include "syscall_types.h"#undef STRUCT#undef STRUCT_SPECIAL /* we patch the ioctl size if necessary. We rely on the fact that no ioctl has all the bits at '1' in the size field */ ie = ioctl_entries; while (ie->target_cmd != 0) { if (((ie->target_cmd >> TARGET_IOC_SIZESHIFT) & TARGET_IOC_SIZEMASK) == TARGET_IOC_SIZEMASK) { arg_type = ie->arg_type; if (arg_type[0] != TYPE_PTR) { fprintf(stderr, "cannot patch size for ioctl 0x%x\n", ie->target_cmd); exit(1); } arg_type++; size = thunk_type_size(arg_type, 0); ie->target_cmd = (ie->target_cmd & ~(TARGET_IOC_SIZEMASK << TARGET_IOC_SIZESHIFT)) | (size << TARGET_IOC_SIZESHIFT); } /* automatic consistency check if same arch */#if defined(__i386__) && defined(TARGET_I386) if (ie->target_cmd != ie->host_cmd) { fprintf(stderr, "ERROR: ioctl: target=0x%x host=0x%x\n", ie->target_cmd, ie->host_cmd); }#endif ie++; }}static inline uint64_t target_offset64(uint32_t word0, uint32_t word1){#ifdef TARGET_WORDS_BIG_ENDIAN return ((uint64_t)word0 << 32) | word1;#else return ((uint64_t)word1 << 32) | word0;#endif}#ifdef TARGET_NR_truncate64static inline long target_truncate64(void *cpu_env, const char *arg1, long arg2, long arg3, long arg4){#ifdef TARGET_ARM if (((CPUARMState *)cpu_env)->eabi) { arg2 = arg3; arg3 = arg4; }#endif return get_errno(truncate64(arg1, target_offset64(arg2, arg3)));}#endif#ifdef TARGET_NR_ftruncate64static inline long target_ftruncate64(void *cpu_env, long arg1, long arg2, long arg3, long arg4){#ifdef TARGET_ARM if (((CPUARMState *)cpu_env)->eabi) { arg2 = arg3; arg3 = arg4; }#endif return get_errno(ftruncate64(arg1, target_offset64(arg2, arg3)));}#endifstatic inline void target_to_host_timespec(struct timespec *host_ts, target_ulong target_addr){ struct target_timespec *target_ts; lock_user_struct(target_ts, target_addr, 1); host_ts->tv_sec = tswapl(target_ts->tv_sec); host_ts->tv_nsec = tswapl(target_ts->tv_nsec); unlock_user_struct(target_ts, target_addr, 0);}static inline void host_to_target_timespec(target_ulong target_addr, struct timespec *host_ts){ struct target_timespec *target_ts; lock_user_struct(target_ts, target_addr, 0); target_ts->tv_sec = tswapl(host_ts->tv_sec); target_ts->tv_nsec = tswapl(host_ts->tv_nsec); unlock_user_struct(target_ts, target_addr, 1);}long do_syscall(void *cpu_env, int num, long arg1, long arg2, long arg3, long arg4, long arg5, long arg6){ long ret; struct stat st; struct statfs stfs; void *p; #ifdef DEBUG gemu_log("syscall %d", num);#endif switch(num) { case TARGET_NR_exit:#ifdef HAVE_GPROF _mcleanup();#endif gdb_exit(cpu_env, arg1); /* XXX: should free thread stack and CPU env */ _exit(arg1); ret = 0; /* avoid warning */ break; case TARGET_NR_read: page_unprotect_range(arg2, arg3); p = lock_user(arg2, arg3, 0); ret = get_errno(read(arg1, p, arg3)); unlock_user(p, arg2, ret); break; case TARGET_NR_write: p = lock_user(arg2, arg3, 1); ret = get_errno(write(arg1, p, arg3)); unlock_user(p, arg2, 0); break; case TARGET_NR_open: p = lock_user_string(arg1); ret = get_errno(open(path(p), target_to_host_bitmask(arg2, fcntl_flags_tbl), arg3)); unlock_user(p, arg1, 0); break; case TARGET_NR_close: ret = get_errno(close(arg1)); break; case TARGET_NR_brk: ret = do_brk(arg1); break; case TARGET_NR_fork: ret = get_errno(do_fork(cpu_env, SIGCHLD, 0)); break; case TARGET_NR_waitpid: { int status; ret = get_errno(waitpid(arg1, &status, arg3)); if (!is_error(ret) && arg2) tput32(arg2, status); } break; case TARGET_NR_creat: p = lock_user_string(arg1); ret = get_errno(creat(p, arg2)); unlock_user(p, arg1, 0); break; case TARGET_NR_link: { void * p2; p = lock_user_string(arg1); p2 = lock_user_string(arg2); ret = get_errno(link(p, p2)); unlock_user(p2, arg2, 0); unlock_user(p, arg1, 0); } break; case TARGET_NR_unlink: p = lock_user_string(arg1); ret = get_errno(unlink(p)); unlock_user(p, arg1, 0); break; case TARGET_NR_execve: { char **argp, **envp; int argc, envc; target_ulong gp; target_ulong guest_argp; target_ulong guest_envp; target_ulong addr; char **q; argc = 0; guest_argp = arg2; for (gp = guest_argp; tgetl(gp); gp++) argc++; envc = 0; guest_envp = arg3; for (gp = guest_envp; tgetl(gp); gp++) envc++; argp = alloca((argc + 1) * sizeof(void *)); envp = alloca((envc + 1) * sizeof(void *)); for (gp = guest_argp, q = argp; ; gp += sizeof(target_ulong), q++) { addr = tgetl(gp); if (!addr) break; *q = lock_user_string(addr); } *q = NULL; for (gp = guest_envp, q = envp; ; gp += sizeof(target_ulong), q++) { addr = tgetl(gp); if (!addr) break; *q = lock_user_string(addr); } *q = NULL; p = lock_user_string(arg1); ret = get_errno(execve(p, argp, envp)); unlock_user(p, arg1, 0); for (gp = guest_argp, q = argp; *q; gp += sizeof(target_ulong), q++) { addr = tgetl(gp); unlock_user(*q, addr, 0); } for (gp = guest_envp, q = envp; *q; gp += sizeof(target_ulong), q++) { addr = tgetl(gp); unlock_user(*q, addr, 0); } } break; case TARGET_NR_chdir: p = lock_user_string(arg1); ret = get_errno(chdir(p)); unlock_user(p, arg1, 0); break;#ifdef TARGET_NR_time case TARGET_NR_time: { time_t host_time; ret = get_errno(time(&host_time)); if (!is_error(ret) && arg1) tputl(arg1, host_time); } break;#endif case TARGET_NR_mknod: p = lock_user_string(arg1); ret = get_errno(mknod(p, arg2, arg3)); unlock_user(p, arg1, 0); break; case TARGET_NR_chmod: p = lock_user_string(arg1); ret = get_errno(chmod(p, arg2)); unlock_user(p, arg1, 0); break;#ifdef TARGET_NR_break case TARGET_NR_break: goto unimplemented;#endif#ifdef TARGET_NR_oldstat case TARGET_NR_oldstat: goto unimplemented;#endif case TARGET_NR_lseek: ret = get_errno(lseek(arg1, arg2, arg3)); break; case TARGET_NR_getpid: ret = get_errno(getpid()); break; case TARGET_NR_mount: /* need to look at the data field */ goto unimplemented; case TARGET_NR_umount: p = lock_user_string(arg1); ret = get_errno(umount(p)); unlock_user(p, arg1, 0); break; case TARGET_NR_stime: { time_t host_time; host_time = tgetl(arg1); ret = get_errno(stime(&host_time)); } break; case TARGET_NR_ptrace: goto unimplemented; case TARGET_NR_alarm: ret = alarm(arg1); break;#ifdef TARGET_NR_oldfstat case TARGET_NR_oldfstat: goto unimplemented;#endif case TARGET_NR_pause: ret = get_errno(pause()); break; case TARGET_NR_utime: { struct utimbuf tbuf, *host_tbuf; struct target_utimbuf *target_tbuf; if (arg2) { lock_user_struct(target_tbuf, arg2, 1); tbuf.actime = tswapl(target_tbuf->actime); tbuf.modtime = tswapl(target_tbuf->modtime); unlock_user_struct(target_tbuf, arg2, 0); host_tbuf = &tbuf; } else { host_tbuf = NULL; } p = lock_user_string(arg1); ret = get_errno(utime(p, host_tbuf)); unlock_user(p, arg1, 0); } break; case TARGET_NR_utimes: { struct timeval *tvp, tv[2]; if (arg2) { target_to_host_timeval(&tv[0], arg2); target_to_host_timeval(&tv[1], arg2 + sizeof (struct target_timeval)); tvp = tv; } else { tvp = NULL; } p = lock_user_string(arg1); ret = get_errno(utimes(p, tvp)); unlock_user(p, arg1, 0); } break;#ifdef TARGET_NR_stty case TARGET_NR_stty: goto unimplemented;#endif#ifdef TARGET_NR_gtty case TARGET_NR_gtty: goto unimplemented;#endif case TARGET_NR_access: p = lock_user_string(arg1); ret = get_errno(access(p, arg2)); unlock_user(p, arg1, 0); break; case TARGET_NR_nice: ret = get_errno(nice(arg1)); break;#ifdef TARGET_NR_ftime case TARGET_NR_ftime: goto unimplemented;#endif case TARGET_NR_sync: sync(); ret = 0; break; case TARGET_NR_kill: ret = get_errno(kill(arg1, arg2)); break; case TARGET_NR_rename: { void *p2; p = lock_user_string(arg1); p2 = lock_user_string(arg2); ret = get_errno(rename(p, p2)); unlock_user(p2, arg2, 0); unlock_user(p, arg1, 0); } break; case TARGET_NR_mkdir: p = lock_user_string(arg1); ret = get_errno(mkdir(p, arg2)); unlock_user(p, arg1, 0); break; case TARGET_NR_rmdir: p = lock_user_string(arg1);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -