📄 syscall.c
字号:
struct ss_rusage{ struct ss_timeval ss_ru_utime; struct ss_timeval ss_ru_stime; sword_t ss_ru_maxrss; sword_t ss_ru_ixrss; sword_t ss_ru_idrss; sword_t ss_ru_isrss; sword_t ss_ru_minflt; sword_t ss_ru_majflt; sword_t ss_ru_nswap; sword_t ss_ru_inblock; sword_t ss_ru_oublock; sword_t ss_ru_msgsnd; sword_t ss_ru_msgrcv; sword_t ss_ru_nsignals; sword_t ss_ru_nvcsw; sword_t ss_ru_nivcsw;};struct ss_timezone{ sword_t ss_tz_minuteswest; /* minutes west of Greenwich */ sword_t ss_tz_dsttime; /* type of dst correction */};struct ss_rlimit{ int ss_rlim_cur; /* current (soft) limit */ int ss_rlim_max; /* maximum value for rlim_cur */};/* open(2) flags for SimpleScalar target, syscall.c automagically maps between these codes to/from host open(2) flags */#define SS_O_RDONLY 0#define SS_O_WRONLY 1#define SS_O_RDWR 2#define SS_O_APPEND 0x0008#define SS_O_CREAT 0x0200#define SS_O_TRUNC 0x0400#define SS_O_EXCL 0x0800#define SS_O_NONBLOCK 0x4000#define SS_O_NOCTTY 0x8000#define SS_O_SYNC 0x2000/* open(2) flags translation table for SimpleScalar target */struct { int ss_flag; int local_flag;} ss_flag_table[] = { /* target flag */ /* host flag */#ifdef _MSC_VER { SS_O_RDONLY, _O_RDONLY }, { SS_O_WRONLY, _O_WRONLY }, { SS_O_RDWR, _O_RDWR }, { SS_O_APPEND, _O_APPEND }, { SS_O_CREAT, _O_CREAT }, { SS_O_TRUNC, _O_TRUNC }, { SS_O_EXCL, _O_EXCL },#ifdef _O_NONBLOCK { SS_O_NONBLOCK, _O_NONBLOCK },#endif#ifdef _O_NOCTTY { SS_O_NOCTTY, _O_NOCTTY },#endif#ifdef _O_SYNC { SS_O_SYNC, _O_SYNC },#endif#else /* !_MSC_VER */ { SS_O_RDONLY, O_RDONLY }, { SS_O_WRONLY, O_WRONLY }, { SS_O_RDWR, O_RDWR }, { SS_O_APPEND, O_APPEND }, { SS_O_CREAT, O_CREAT }, { SS_O_TRUNC, O_TRUNC }, { SS_O_EXCL, O_EXCL }, { SS_O_NONBLOCK, O_NONBLOCK }, { SS_O_NOCTTY, O_NOCTTY },#ifdef O_SYNC { SS_O_SYNC, O_SYNC },#endif#endif /* _MSC_VER */};#define SS_NFLAGS (sizeof(ss_flag_table)/sizeof(ss_flag_table[0]))#endif /* !MD_CROSS_ENDIAN *//* syscall proxy handler, architect registers and memory are assumed to be precise when this function is called, register and memory are updated with the results of the sustem call */voidsys_syscall(struct regs_t *regs, /* registers to access */ mem_access_fn mem_fn, /* generic memory accessor */ struct mem_t *mem, /* memory space to access */ md_inst_t inst, /* system call inst */ int traceable) /* traceable system call? */{ word_t syscode = regs->regs_R[2]; /* first, check if an EIO trace is being consumed... */ if (traceable && sim_eio_fd != NULL) { eio_read_trace(sim_eio_fd, sim_num_insn, regs, mem_fn, mem, inst); /* fini... */ return; }#ifdef MD_CROSS_ENDIAN else if (syscode == SS_SYS_exit) { /* exit jumps to the target set in main() */ longjmp(sim_exit_buf, /* exitcode + fudge */regs->regs_R[4]+1); } else fatal("cannot execute PISA system call on cross-endian host");#else /* !MD_CROSS_ENDIAN */ /* no, OK execute the live system call... */ switch (syscode) { case SS_SYS_exit: /* exit jumps to the target set in main() */ longjmp(sim_exit_buf, /* exitcode + fudge */regs->regs_R[4]+1); break;#if 0 case SS_SYS_fork: /* FIXME: this is broken... */ regs->regs_R[2] = fork(); if (regs->regs_R[2] != -1) { regs->regs_R[7] = 0; /* parent process */ if (regs->regs_R[2] != 0) regs->regs_R[3] = 0; } else fatal("SYS_fork failed"); break;#endif#if 0 case SS_SYS_vfork: /* FIXME: this is broken... */ int r31_parent = regs->regs_R[31]; /* pid */regs->regs_R[2] = vfork(); if (regs->regs_R[2] != -1) regs->regs_R[7] = 0; else fatal("vfork() in SYS_vfork failed"); if (regs->regs_R[2] != 0) { regs->regs_R[3] = 0; regs->regs_R[7] = 0; regs->regs_R[31] = r31_parent; } break;#endif case SS_SYS_read: { char *buf; /* allocate same-sized input buffer in host memory */ if (!(buf = (char *)calloc(/*nbytes*/regs->regs_R[6], sizeof(char)))) fatal("out of memory in SYS_read"); /* read data from file */ /*nread*/regs->regs_R[2] = read(/*fd*/regs->regs_R[4], buf, /*nbytes*/regs->regs_R[6]); /* check for error condition */ if (regs->regs_R[2] != -1) regs->regs_R[7] = 0; else { /* got an error, return details */ regs->regs_R[2] = errno; regs->regs_R[7] = 1; } /* copy results back into host memory */ mem_bcopy(mem_fn, mem, Write, /*buf*/regs->regs_R[5], buf, /*nread*/regs->regs_R[2]); /* done with input buffer */ free(buf); } break; case SS_SYS_write: { char *buf; /* allocate same-sized output buffer in host memory */ if (!(buf = (char *)calloc(/*nbytes*/regs->regs_R[6], sizeof(char)))) fatal("out of memory in SYS_write"); /* copy inputs into host memory */ mem_bcopy(mem_fn, mem, Read, /*buf*/regs->regs_R[5], buf, /*nbytes*/regs->regs_R[6]); /* write data to file */ if (sim_progfd && MD_OUTPUT_SYSCALL(regs)) { /* redirect program output to file */ /*nwritten*/regs->regs_R[2] = fwrite(buf, 1, /*nbytes*/regs->regs_R[6], sim_progfd); } else { /* perform program output request */ /*nwritten*/regs->regs_R[2] = write(/*fd*/regs->regs_R[4], buf, /*nbytes*/regs->regs_R[6]); } /* check for an error condition */ if (regs->regs_R[2] == regs->regs_R[6]) /*result*/regs->regs_R[7] = 0; else { /* got an error, return details */ regs->regs_R[2] = errno; regs->regs_R[7] = 1; } /* done with output buffer */ free(buf); } break; case SS_SYS_open: { char buf[MAXBUFSIZE]; unsigned int i; int ss_flags = regs->regs_R[5], local_flags = 0; /* translate open(2) flags */ for (i=0; i<SS_NFLAGS; i++) { if (ss_flags & ss_flag_table[i].ss_flag) { ss_flags &= ~ss_flag_table[i].ss_flag; local_flags |= ss_flag_table[i].local_flag; } } /* any target flags left? */ if (ss_flags != 0) fatal("syscall: open: cannot decode flags: 0x%08x", ss_flags); /* copy filename to host memory */ mem_strcpy(mem_fn, mem, Read, /*fname*/regs->regs_R[4], buf); /* open the file */ /*fd*/regs->regs_R[2] = open(buf, local_flags, /*mode*/regs->regs_R[6]); /* check for an error condition */ if (regs->regs_R[2] != -1) regs->regs_R[7] = 0; else { /* got an error, return details */ regs->regs_R[2] = errno; regs->regs_R[7] = 1; } } break; case SS_SYS_close: /* don't close stdin, stdout, or stderr as this messes up sim logs */ if (/*fd*/regs->regs_R[4] == 0 || /*fd*/regs->regs_R[4] == 1 || /*fd*/regs->regs_R[4] == 2) { regs->regs_R[7] = 0; break; } /* close the file */ regs->regs_R[2] = close(/*fd*/regs->regs_R[4]); /* check for an error condition */ if (regs->regs_R[2] != -1) regs->regs_R[7] = 0; else { /* got an error, return details */ regs->regs_R[2] = errno; regs->regs_R[7] = 1; } break; case SS_SYS_creat: { char buf[MAXBUFSIZE]; /* copy filename to host memory */ mem_strcpy(mem_fn, mem, Read, /*fname*/regs->regs_R[4], buf); /* create the file */ /*fd*/regs->regs_R[2] = creat(buf, /*mode*/regs->regs_R[5]); /* check for an error condition */ if (regs->regs_R[2] != -1) regs->regs_R[7] = 0; else { /* got an error, return details */ regs->regs_R[2] = errno; regs->regs_R[7] = 1; } } break; case SS_SYS_unlink: { char buf[MAXBUFSIZE]; /* copy filename to host memory */ mem_strcpy(mem_fn, mem, Read, /*fname*/regs->regs_R[4], buf); /* delete the file */ /*result*/regs->regs_R[2] = unlink(buf); /* check for an error condition */ if (regs->regs_R[2] != -1) regs->regs_R[7] = 0; else { /* got an error, return details */ regs->regs_R[2] = errno; regs->regs_R[7] = 1; } } break; case SS_SYS_chdir: { char buf[MAXBUFSIZE]; /* copy filename to host memory */ mem_strcpy(mem_fn, mem, Read, /*fname*/regs->regs_R[4], buf); /* change the working directory */ /*result*/regs->regs_R[2] = chdir(buf); /* check for an error condition */ if (regs->regs_R[2] != -1) regs->regs_R[7] = 0; else { /* got an error, return details */ regs->regs_R[2] = errno; regs->regs_R[7] = 1; } } break; case SS_SYS_chmod: { char buf[MAXBUFSIZE]; /* copy filename to host memory */ mem_strcpy(mem_fn, mem, Read, /*fname*/regs->regs_R[4], buf); /* chmod the file */ /*result*/regs->regs_R[2] = chmod(buf, /*mode*/regs->regs_R[5]); /* check for an error condition */ if (regs->regs_R[2] != -1) regs->regs_R[7] = 0; else { /* got an error, return details */ regs->regs_R[2] = errno; regs->regs_R[7] = 1; } } break; case SS_SYS_chown:#ifdef _MSC_VER warn("syscall chown() not yet implemented for MSC..."); regs->regs_R[7] = 0;#else /* !_MSC_VER */ { char buf[MAXBUFSIZE]; /* copy filename to host memory */ mem_strcpy(mem_fn, mem, Read, /*fname*/regs->regs_R[4], buf); /* chown the file */ /*result*/regs->regs_R[2] = chown(buf, /*owner*/regs->regs_R[5], /*group*/regs->regs_R[6]); /* check for an error condition */ if (regs->regs_R[2] != -1) regs->regs_R[7] = 0; else { /* got an error, return details */ regs->regs_R[2] = errno; regs->regs_R[7] = 1; } }#endif /* _MSC_VER */ break; case SS_SYS_brk: { md_addr_t addr; /* round the new heap pointer to the its page boundary */ addr = ROUND_UP(/*base*/regs->regs_R[4], MD_PAGE_SIZE); /* check whether heap area has merged with stack area */ if (addr >= ld_brk_point && addr < (md_addr_t)regs->regs_R[29]) { regs->regs_R[2] = 0; regs->regs_R[7] = 0; ld_brk_point = addr; } else { /* out of address space, indicate error */ regs->regs_R[2] = ENOMEM; regs->regs_R[7] = 1; } } break; case SS_SYS_lseek: /* seek into file */ regs->regs_R[2] = lseek(/*fd*/regs->regs_R[4], /*off*/regs->regs_R[5], /*dir*/regs->regs_R[6]); /* check for an error condition */ if (regs->regs_R[2] != -1) regs->regs_R[7] = 0; else { /* got an error, return details */ regs->regs_R[2] = errno; regs->regs_R[7] = 1; } break; case SS_SYS_getpid: /* get the simulator process id */ /*result*/regs->regs_R[2] = getpid(); /* check for an error condition */ if (regs->regs_R[2] != -1) regs->regs_R[7] = 0; else { /* got an error, return details */ regs->regs_R[2] = errno; regs->regs_R[7] = 1; } break; case SS_SYS_getuid:#ifdef _MSC_VER warn("syscall getuid() not yet implemented for MSC..."); regs->regs_R[7] = 0;#else /* !_MSC_VER */ /* get current user id */ /*first result*/regs->regs_R[2] = getuid(); /* get effective user id */ /*second result*/regs->regs_R[3] = geteuid(); /* check for an error condition */ if (regs->regs_R[2] != -1) regs->regs_R[7] = 0; else { /* got an error, return details */ regs->regs_R[2] = errno; regs->regs_R[7] = 1; }#endif /* _MSC_VER */ break; case SS_SYS_access: { char buf[MAXBUFSIZE]; /* copy filename to host memory */ mem_strcpy(mem_fn, mem, Read, /*fName*/regs->regs_R[4], buf); /* check access on the file */ /*result*/regs->regs_R[2] = access(buf, /*mode*/regs->regs_R[5]); /* check for an error condition */ if (regs->regs_R[2] != -1) regs->regs_R[7] = 0; else {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -