void runtime·args(int32 c, uint8 **v) { argc = c; argv = v; if(runtime·sysargs != nil) runtime·sysargs(c, v); }
VOID SyscallEntry(THREADID threadIndex, CONTEXT *ctxt, SYSCALL_STANDARD std, VOID *v) { sysargs(PIN_GetSyscallNumber(ctxt, std), PIN_GetSyscallArgument(ctxt, std, 0), PIN_GetSyscallArgument(ctxt, std, 1), PIN_GetSyscallArgument(ctxt, std, 2), PIN_GetSyscallArgument(ctxt, std, 3), PIN_GetSyscallArgument(ctxt, std, 4), PIN_GetSyscallArgument(ctxt, std, 5)); }
void appserver_t::syscall(uint8_t* magicmem) { uint32_t which, pid; int32_t arg0, arg1, arg2, arg3; int32_t ret = 0; int freq = 100000000; int clk_tck = 100; uint32_t* buf = (uint32_t*)magicmem; which = htif->htotl(buf[1]); arg0 = htif->htotl(buf[2]); arg1 = htif->htotl(buf[3]); arg2 = htif->htotl(buf[4]); arg3 = htif->htotl(buf[5]); pid = htif->htotl(buf[6]); strace("syscall# = %d\n", which); if(!processes.count(pid)) { fprintf(stderr,"Syscall from unknown process %d!\n",pid); abort(); } processes[pid].become(); errno = 0; switch (which) { case RAMP_SYSCALL_proc_init: strace("SYSCALL_proc_init called!\n"); { assert(processes.count(arg0) == 0); processes[arg0] = processes[pid]; ret = 0; } break; case RAMP_SYSCALL_proc_free: strace("SYSCALL_proc_free called!\n"); { assert(processes.count(arg0) == 1); processes.erase(arg0); ret = 0; } break; case RAMP_SYSCALL_exit: strace("SYSCALL_exit called!\n"); { int status = arg0; exit_code = arg0; do_exit = true; } break; case RAMP_SYSCALL_dup2: { if(arg1 < 0 || processes[pid].fdmap.count(arg0) == 0) { errno = EBADF; ret = -1; } else if(arg0 == arg1) ret = arg0; else { if((ret = dup(processes[pid].fdmap[arg0])) < 0) break; if(processes[pid].fdmap.count(arg1)) close(processes[pid].fdmap[arg1]); processes[pid].fdmap[arg1] = ret; ret = arg1; } strace("SYSCALL_dup2(%d,%d) == %d called!\n",arg0,arg1,ret); } break; case RAMP_SYSCALL_utime: { sysargs_t sysargs_f(*htif, arg0, RAMP_MAXPATH); char* file = (char*)sysargs_f.get_buffer(); struct utimbuf ut; ut.actime = arg1; ut.modtime = arg2; ret = utime(file,&ut); strace("SYSCALL_utime(\"%s\",%d,%d) == %d called!\n",file,arg1,arg2,ret); } break; case RAMP_SYSCALL_umask: { ret = umask(arg0); } break; case RAMP_SYSCALL_read: { int fd = -1; if(processes[pid].fdmap.count(arg0) == 0) { ret = (uint32_t)-1; errno = EBADF; } else { fd = processes[pid].fdmap[arg0]; sysargs_t sysargs(*htif, arg1, arg2); if(processes[pid].dirmap.count(arg0)) { struct ramp_dirent { uint64_t d_ino; uint64_t d_off; uint16_t d_reclen; uint8_t d_type; char d_name[256]; } *rde = (struct ramp_dirent*)sysargs.buffer(); if(arg2 < sizeof(struct ramp_dirent)) { ret = -1; errno = EINVAL; } else { struct dirent* de = readdir(processes[pid].dirmap[arg0]); if(de == NULL) ret = 0; else { ret = 8+8+2+1+strnlen(de->d_name,256); rde->d_ino = htif->htotll(de->d_ino); rde->d_off = htif->htotll(de->d_off); rde->d_reclen = htif->htots(ret); rde->d_type = de->d_type; strncpy(rde->d_name,de->d_name,256); } } } else ret = read(fd, sysargs.buffer(), arg2); sysargs.put_buffer(); } strace("SYSCALL_read(%d(%d),0x%x,%d) == %d called!\n",arg0,fd,arg1,arg2,ret); } break; case RAMP_SYSCALL_pread: { int fd = -1; if(processes[pid].fdmap.count(arg0) == 0) { ret = (uint32_t)-1; errno = EBADF; } else { fd = processes[pid].fdmap[arg0]; sysargs_t sysargs(*htif, arg1, arg2); ret = pread(fd, sysargs.buffer(), arg2, arg3); sysargs.put_buffer(); } strace("SYSCALL_pread(%d(%d),0x%x,%d,%d) == %d called!\n",arg0,fd,arg1,arg2,arg3,ret); } break; case RAMP_SYSCALL_write: { printf("syscall write\n"); int fd = -1; if(processes[pid].fdmap.count(arg0) == 0) { ret = (uint32_t)-1; errno = EBADF; } else { fd = processes[pid].fdmap[arg0]; sysargs_t sysargs(*htif, arg1, arg2); char * args_string = (char *)sysargs.get_buffer(); //fprintf(stderr, "\nlength = %d\n", arg2); #if 1 if(outfp!=NULL) { if(file_size > 0) { ret = fwrite(args_string, 1, arg2, outfp); file_size-=arg2; //fprintf(stderr, "\nfile size=%d\n", file_size); //fwrite(sysargs.get_buffer(), 1, arg2, stderr); } else { ret = write(fd,args_string,arg2); fclose(outfp); outfp = NULL; } } else { if(*args_string==0x02) { int i; char len_string[10]; char * file_name=NULL, *file_path=NULL; //fprintf(stderr, "\nlength = %d, Contents of the buffer:", arg2); for(i=1; i<arg2; ++i) { if(args_string[i] == '/') file_name = args_string + i; if(args_string[i] == 0x02) args_string[i] = 0x00; } //strncpy(len_string, args_string + 1, 9); //len_string[9] = 0; args_string[10] = 0; file_size = atoi(args_string + 1); file_path = args_string + 11; if(file_path[0] == '/') file_path = file_path + 1; if(file_name != NULL) { char command[256]; file_name++; for(i = 0; file_path + i != file_name; ++i) { if(file_path[i] == '/') { file_path[i] = 0; fprintf(stderr, "Create Dir: %s\n", file_path); mkdir(file_path, 0644); file_path[i] = '/'; } } } fprintf(stderr, "\nfile size=%d, file path=%s, file_name=%s\n", file_size, file_path, file_name != NULL ? file_name : "(NULL)"); outfp = fopen(file_path, "wb"); if(outfp==NULL) { fprintf(stderr, "Cannot create file %s on PC\n", file_size, file_name); exit(0); } ret = arg2; } else { ret = write(fd,args_string,arg2); } } #endif } strace("SYSCALL_write(%d(%d),0x%x,%d) == %d called!\n",arg0,fd,arg1,arg2,ret); } break; case RAMP_SYSCALL_pwrite: { int fd = -1; if(processes[pid].fdmap.count(arg0) == 0) { ret = (uint32_t)-1; errno = EBADF; } else { fd = processes[pid].fdmap[arg0]; sysargs_t sysargs(*htif, arg1, arg2); ret = pwrite(fd,sysargs.get_buffer(),arg2,arg3); } strace("SYSCALL_pwrite(%d(%d),0x%x,%d,%d) == %d called!\n",arg0,fd,arg1,arg2,arg3,ret); } break; case RAMP_SYSCALL_chmod: { sysargs_t sysargs_f(*htif, arg0, RAMP_MAXPATH); char* file = (char*)sysargs_f.get_buffer(); ret = chmod(file,arg1); strace("SYSCALL_chmod(\"%s\",%d) == %d called!\n",file,arg1,ret); } break; case RAMP_SYSCALL_access: { sysargs_t sysargs_f(*htif, arg0, RAMP_MAXPATH); char* file = (char*)sysargs_f.get_buffer(); ret = access(file,arg1); strace("SYSCALL_access(\"%s\",%d) == %d called!\n",file,arg1,ret); } break; case RAMP_SYSCALL_kdup: // duplicate an fd into the kernel { if(processes[pid].fdmap.count(arg0) == 0) { ret = (uint32_t)-1; errno = EBADF; } else { int fd = processes[pid].fdmap[arg0]; int newfd = dup(fd); if (newfd != -1) processes[0].fdmap[ret = processes[0].next_fd()] = newfd; else ret = (uint32_t)-1; } strace("SYSCALL_kdup(%d) == %d called!\n",arg0,ret); } break; case RAMP_SYSCALL_dup: { if(processes[pid].fdmap.count(arg0) == 0) { ret = (uint32_t)-1; errno = EBADF; } else { int fd = processes[pid].fdmap[arg0]; int newfd = dup(fd); if (newfd != -1) processes[pid].fdmap[ret = processes[pid].next_fd()] = newfd; else ret = (uint32_t)-1; } strace("SYSCALL_dup(%d) == %d called!\n",arg0,ret); } break; case RAMP_SYSCALL_open: { sysargs_t sysargs_f(*htif, arg0, RAMP_MAXPATH); char* file = (char*)sysargs_f.get_buffer(); int flag = arg1; //sysargs_t::convert_flag(arg1,false); int mode = arg2; DIR* d = NULL; int fd = -1; struct stat st; if(!(flag & O_WRONLY) && !(flag & O_RDWR) && stat(file,&st) != -1 && (st.st_mode & S_IFDIR)) { if(d = opendir(file)) fd = dirfd(d); } else fd = open(file, flag, mode); if (fd != -1) { processes[pid].fdmap[ret = processes[pid].next_fd()] = fd; if(d) processes[pid].dirmap[ret] = d; } else ret = (uint32_t)-1; strace("SYSCALL_open(\"%s\",0x%x(0x%x),0x%x) == %d(%d) called!\n",file,arg1,flag,mode,ret,fd); } break; case RAMP_SYSCALL_fcntl: { if(processes[pid].fdmap.count(arg0) == 0) { ret = (uint32_t)-1; errno = EBADF; } else { ret = fcntl(processes[pid].fdmap[arg0],arg1,arg2); if(ret != -1) { if(arg1 == F_DUPFD) { int oldfd = ret; processes[pid].fdmap[ret = processes[pid].next_fd(arg2)] = oldfd; } } } strace("SYSCALL_fcntl(%d,%d,0x%x) == %d called!\n",arg0,arg1,arg2,ret); } break; case RAMP_SYSCALL_close: { if(processes[pid].fdmap.count(arg0) == 0) { errno = EBADF; ret = (uint32_t)-1; } else { ret = close(processes[pid].fdmap[arg0]); if(ret == 0) { processes[pid].fdmap.erase(arg0); processes[pid].dirmap.erase(arg0); } } strace("SYSCALL_close(%d) == %d called!\n",arg0,ret); } break; case RAMP_SYSCALL_lseek: strace("SYSCALL_lseek called!\n"); { if(processes[pid].fdmap.count(arg0) == 0) { ret = (uint32_t)-1; errno = EBADF; } else { int fd = processes[pid].fdmap[arg0]; ret = lseek(fd, (off_t)arg1, arg2); } } break; case RAMP_SYSCALL_link: strace("SYSCALL_link called!\n"); { sysargs_t sysargs_f0(*htif, arg0, RAMP_MAXPATH); char* file0 = (char*)sysargs_f0.get_buffer(); sysargs_t sysargs_f1(*htif, arg1, RAMP_MAXPATH); char* file1 = (char*)sysargs_f1.get_buffer(); ret = link(file0,file1); } break; case RAMP_SYSCALL_unlink: strace("SYSCALL_unlink called!\n"); { sysargs_t sysargs_f(*htif, arg0, RAMP_MAXPATH); char* file = (char*)sysargs_f.get_buffer(); ret = unlink(file); } break; case RAMP_SYSCALL_chdir: strace("SYSCALL_chdir called!\n"); { sysargs_t sysargs_f(*htif, arg0, RAMP_MAXPATH); char* file = (char*)sysargs_f.get_buffer(); ret = chdir(file); } break; case RAMP_SYSCALL_getcwd: strace("SYSCALL_getcwd called!\n"); { sysargs_t sysargs(*htif, arg0, arg1); char* ret2 = getcwd((char*)sysargs.buffer(),arg1); ret = ret2 ? arg0 : 0; sysargs.put_buffer(); } break; case RAMP_SYSCALL_stat: strace("SYSCALL_stat called!\n"); { sysargs_t sysargs_f(*htif, arg0, RAMP_MAXPATH); char* file = (char*)sysargs_f.get_buffer(); sysargs_t sysargs(*htif, arg1, sizeof(newlib_stat)); struct stat linux_stat; ret = stat(file, &linux_stat); sysargs.convert_stat(&linux_stat); if (ret == 0) { sysargs.put_buffer(); } } break; case RAMP_SYSCALL_fstat: strace("SYSCALL_fstat called!\n"); { if(processes[pid].fdmap.count(arg0) == 0) ret = (uint32_t)-1; else { int fd = processes[pid].fdmap[arg0]; sysargs_t sysargs(*htif, arg1, sizeof(newlib_stat)); struct stat linux_stat; ret = fstat(fd, &linux_stat); sysargs.convert_stat(&linux_stat); if (ret == 0) sysargs.put_buffer(); } } break; case RAMP_SYSCALL_lstat: strace("SYSCALL_lstat called!\n"); { sysargs_t sysargs_f(*htif, arg0, RAMP_MAXPATH); char* file = (char*)sysargs_f.get_buffer(); sysargs_t sysargs(*htif, arg1, sizeof(newlib_stat)); struct stat linux_stat; ret = lstat(file, &linux_stat); sysargs.convert_stat(&linux_stat); if (ret == 0) { sysargs.put_buffer(); } } break; case RAMP_SYSCALL_tcsetattr: strace("SYSCALL_tcsetattr called!\n"); if(processes[pid].fdmap.count(arg0) == 0) { ret = (uint32_t)-1; errno = EBADF; } else { int fd = processes[pid].fdmap[arg0]; sysargs_t sysargs(*htif, arg2, sizeof(struct termios)); struct termios* tios = (struct termios*)sysargs.get_buffer(); tios->c_iflag = htif->htotl(tios->c_iflag); tios->c_oflag = htif->htotl(tios->c_oflag); tios->c_cflag = htif->htotl(tios->c_cflag); tios->c_lflag = htif->htotl(tios->c_lflag); tios->c_line = htif->htotl(tios->c_line); tios->c_ispeed = htif->htotl(tios->c_ispeed); tios->c_ospeed = htif->htotl(tios->c_ospeed); ret = tcsetattr(fd,arg1,tios); } break; case RAMP_SYSCALL_tcgetattr: strace("SYSCALL_tcgetattr called!\n"); if(processes[pid].fdmap.count(arg0) == 0) { ret = (uint32_t)-1; errno = EBADF; } else { int fd = processes[pid].fdmap[arg0]; sysargs_t sysargs(*htif, arg1, sizeof(struct termios)); struct termios* tios = (struct termios*)sysargs.buffer(); ret = tcgetattr(fd,tios); if (ret == 0) { tios->c_iflag = htif->htotl(tios->c_iflag); tios->c_oflag = htif->htotl(tios->c_oflag); tios->c_cflag = htif->htotl(tios->c_cflag); tios->c_lflag = htif->htotl(tios->c_lflag); tios->c_line = htif->htotl(tios->c_line); tios->c_ispeed = htif->htotl(tios->c_ispeed); tios->c_ospeed = htif->htotl(tios->c_ospeed); sysargs.put_buffer(); } } break; case RAMP_SYSCALL_time: strace("SYSCALL_time called!\n"); { static int t0 = 0; if(t0 == 0) t0 = time(NULL); ret = t0; } break; default: printf("not serving system call #%d. panic!\n", which); exit(-1); break; } processes[pid].update(); strace("Syscall result %d\n",ret); buf[7] = htif->htotl(1); // set_fromhost(1) buf[0] = htif->htotl(0); // clear tohost buf[1] = htif->htotl(ret); buf[2] = htif->htotl(errno); htif->lmem().write(htif->get_magicmemaddr(),32,(uint8_t*)buf); nsyscalls++; }