src/Emu/AlphaLinux/AlphaLinuxSyscallConv.cpp

説明を見る。
00001 // 
00002 // Copyright (c) 2005-2008 Kenichi Watanabe.
00003 // Copyright (c) 2005-2008 Yasuhiro Watari.
00004 // Copyright (c) 2005-2008 Hironori Ichibayashi.
00005 // Copyright (c) 2008-2009 Kazuo Horio.
00006 // Copyright (c) 2009-2013 Naruki Kurata.
00007 // Copyright (c) 2005-2013 Ryota Shioya.
00008 // Copyright (c) 2005-2013 Masahiro Goshima.
00009 // 
00010 // This software is provided 'as-is', without any express or implied
00011 // warranty. In no event will the authors be held liable for any damages
00012 // arising from the use of this software.
00013 // 
00014 // Permission is granted to anyone to use this software for any purpose,
00015 // including commercial applications, and to alter it and redistribute it
00016 // freely, subject to the following restrictions:
00017 // 
00018 // 1. The origin of this software must not be misrepresented; you must not
00019 // claim that you wrote the original software. If you use this software
00020 // in a product, an acknowledgment in the product documentation would be
00021 // appreciated but is not required.
00022 // 
00023 // 2. Altered source versions must be plainly marked as such, and must not be
00024 // misrepresented as being the original software.
00025 // 
00026 // 3. This notice may not be removed or altered from any source
00027 // distribution.
00028 // 
00029 // 
00030 
00031 
00032 #include <pch.h>
00033 
00034 #include "Emu/AlphaLinux/AlphaLinuxSyscallConv.h"
00035 
00036 #include "Env/Env.h"
00037 #include "SysDeps/posix.h"
00038 
00039 #include "Emu/Utility/System/ProcessState.h"
00040 #include "Emu/Utility/System/Memory/MemorySystem.h"
00041 #include "Emu/Utility/System/Memory/MemoryUtility.h"
00042 #include "Emu/Utility/System/VirtualSystem.h"
00043 #include "Emu/Utility/System/Syscall/SyscallConstConv.h"
00044 #include "Emu/Utility/OpEmulationState.h"
00045 
00046 #include "Emu/AlphaLinux/AlphaLinuxSyscallID.h"
00047 
00048 
00049 //#define SYSCALL_DEBUG
00050 
00051 using namespace std;
00052 using namespace boost;
00053 using namespace Onikiri;
00054 using namespace Onikiri::EmulatorUtility;
00055 using namespace Onikiri::AlphaLinux;
00056 using namespace Onikiri::POSIX;
00057 
00058 
00059 
00060 // AlphaLinuxSyscallConv
00061 AlphaLinuxSyscallConv::AlphaLinuxSyscallConv(ProcessState* processState) : Linux64SyscallConv(processState)
00062 {
00063 }
00064 
00065 AlphaLinuxSyscallConv::~AlphaLinuxSyscallConv()
00066 {
00067 }
00068 
00069 #ifdef SYSCALL_DEBUG
00070 #define SYSCALLNAME(name, argcnt, argtempl) {syscall_id_##name, #name, argcnt, argtempl}
00071 
00072 namespace {
00073 
00074 // x: int (hexadecimal)
00075 // n: int
00076 // p: pointer
00077 // s: string
00078 
00079 static struct {
00080     unsigned int syscallNo;
00081     const char *const name;
00082     int argcnt;
00083     const char *const argtempl;
00084 } syscallTable[] = {
00085     SYSCALLNAME(exit, 0, ""),
00086     SYSCALLNAME(read, 3, "npn"),
00087     SYSCALLNAME(write, 3, "npn"),
00088     SYSCALLNAME(readv, 3, "npn"),
00089     SYSCALLNAME(writev, 3, "npn"),
00090     SYSCALLNAME(open, 3, "sxx"),
00091     SYSCALLNAME(close, 1, "n"),
00092     SYSCALLNAME(stat, 2, "sp"),
00093     SYSCALLNAME(lstat, 2, "sp"),
00094     SYSCALLNAME(fstat, 2, "np"),
00095     SYSCALLNAME(stat64, 2, "sp"),
00096     SYSCALLNAME(lstat64, 2, "sp"),
00097     SYSCALLNAME(fstat64, 2, "np"),
00098     SYSCALLNAME(lseek, 3, "nxn"),
00099     SYSCALLNAME(truncate, 2, "px"),
00100     SYSCALLNAME(ftruncate, 2, "nx"),
00101     SYSCALLNAME(fcntl, 3, "nnp"),
00102     SYSCALLNAME(flock, 2, "nn"),
00103     SYSCALLNAME(chdir, 1, "p"),
00104     SYSCALLNAME(fchdir, 1, "n"),
00105     SYSCALLNAME(getcwd, 2, "px"),
00106     SYSCALLNAME(mkdir, 2, "sx"),
00107     SYSCALLNAME(rmdir, 1, "s"),
00108     SYSCALLNAME(readlink, 3, "spx"),
00109     SYSCALLNAME(unlink, 1, "s"),
00110     SYSCALLNAME(link, 2, "ss"),
00111     SYSCALLNAME(rename, 2, "ss"),
00112     SYSCALLNAME(mmap, 6, "pxxxnx"),
00113     SYSCALLNAME(mremap, 4, "pxxx"),
00114     SYSCALLNAME(munmap, 2, "px"),
00115     SYSCALLNAME(mprotect, 3, "pxx"),
00116     SYSCALLNAME(chmod, 2, "sx"),
00117     SYSCALLNAME(ioctl, 3, "xxx"),
00118     SYSCALLNAME(times, 1, "p"),
00119     SYSCALLNAME(gettimeofday, 2, "pp"),
00120     SYSCALLNAME(settimeofday, 2, "pp"),
00121 
00122     SYSCALLNAME(uname, 1, "p"),
00123     SYSCALLNAME(brk, 1, "p"),
00124     SYSCALLNAME(osf_getsysinfo, 6, "xxxxxx"),
00125     SYSCALLNAME(osf_setsysinfo, 6, "xxxxxx"),
00126 
00127     SYSCALLNAME(access, 2, "sx"),
00128 
00129     SYSCALLNAME(getxpid, 0, ""),
00130     SYSCALLNAME(gettid, 0, ""),
00131     //SYSCALLNAME(setuid, 1),
00132     //SYSCALLNAME(getuid, 0),
00133     //SYSCALLNAME(seteuid, 1),
00134     SYSCALLNAME(getxuid, 0, ""),
00135     //SYSCALLNAME(setgid, 1),
00136     SYSCALLNAME(getxgid, 0, ""),
00137     //SYSCALLNAME(getgid, 0),
00138     //SYSCALLNAME(setegid, 1),
00139     //SYSCALLNAME(getegid, 0),
00140     //SYSCALLNAME(setreuid, 2),
00141     //SYSCALLNAME(setregid, 2),
00142     SYSCALLNAME(getrusage, 2, "xp"),
00143     SYSCALLNAME(getrlimit, 2, "np"),
00144     SYSCALLNAME(setrlimit, 2, "np"),
00145     SYSCALLNAME(exit_group, 0, ""),
00146     SYSCALLNAME(dup, 1, "n"),
00147 
00148     SYSCALLNAME(rt_sigaction, 3, "xxx"),
00149     SYSCALLNAME(osf_sigprocmask, 3, "xxx"),
00150     SYSCALLNAME(kill, 2, "xx"),
00151     SYSCALLNAME(tgkill, 3, "xxx"),
00152 };
00153 #undef SYSCALLNAME
00154 
00155 } // namespace {
00156 #endif // #ifdef SYSCALL_DEBUG
00157 
00158 
00159 void AlphaLinuxSyscallConv::Execute(OpEmulationState* opState)
00160 {
00161 #ifdef SYSCALL_DEBUG 
00162     static std::ofstream log("syscall.log", std::ios_base::out);
00163 
00164     log << dec << GetVirtualSystem()->GetInsnTick() << "\t";
00165     log << dec << GetArg(0) << " ";
00166     for (size_t i = 0; i < sizeof(syscallTable)/sizeof(syscallTable[0]); i ++) {
00167         if (syscallTable[i].syscallNo == GetArg(0)) {
00168             log << "\t" << syscallTable[i].name << "(";
00169             int argcnt = syscallTable[i].argcnt;
00170             const char *argtempl = syscallTable[i].argtempl;
00171             for (int j = 1; j <= argcnt; j ++) {
00172                 switch (argtempl[j-1]) {
00173                 case 's':
00174                     {
00175                         std::string s = StrCpyToHost( GetMemorySystem(), GetArg(j) );
00176                         log << "0x" << hex << GetArg(j) << dec;
00177                         log << "=\"" << s << "\"";
00178                     }
00179                     break;
00180                 case 'n':
00181                     log << dec << (s64)GetArg(j);
00182                     break;
00183                 case 'p':
00184                 case 'x':
00185                 default:
00186                     log << "0x" << hex << GetArg(j) << dec;
00187                     break;
00188                 }
00189                 if (j != argcnt)
00190                     log << ", ";
00191             }
00192             log << ")";
00193         }
00194     }
00195     log << flush;
00196 #endif // #ifdef SYSCALL_DEBUG
00197 
00198     opState->SetTakenPC( opState->GetPC()+4 );
00199     opState->SetTaken(true);
00200 
00201     SetResult(false, 0);
00202     switch (GetArg(0)) {
00203     case syscall_id_exit:
00204     case syscall_id_exit_group:
00205         syscall_exit(opState);
00206         break;
00207     case syscall_id_read:
00208         syscall_read(opState);
00209         break;
00210     case syscall_id_write:
00211         syscall_write(opState);
00212         break;
00213     case syscall_id_readv:
00214         syscall_readv(opState);
00215         break;
00216     case syscall_id_writev:
00217         syscall_writev(opState);
00218         break;
00219     case syscall_id_open:
00220         syscall_open(opState);
00221         break;
00222     case syscall_id_close:
00223         syscall_close(opState);
00224         break;
00225 
00226     case syscall_id_lseek:
00227         syscall_lseek(opState);
00228         break;
00229     case syscall_id_unlink:
00230         syscall_unlink(opState);
00231         break;
00232     case syscall_id_rename:
00233         syscall_rename(opState);
00234         break;
00235 
00236 
00237     case syscall_id_mmap:
00238         syscall_mmap(opState);
00239         break;
00240     case syscall_id_mremap:
00241         syscall_mremap(opState);
00242         break;
00243     case syscall_id_munmap:
00244         syscall_munmap(opState);
00245         break;
00246     case syscall_id_mprotect:
00247         syscall_mprotect(opState);
00248         break;
00249     case syscall_id_uname:
00250         syscall_uname(opState);
00251         break;
00252     case syscall_id_fcntl:
00253         syscall_fcntl(opState);
00254         break;
00255     case syscall_id_brk:
00256         syscall_brk(opState);
00257         break;
00258     case syscall_id_osf_getsysinfo:
00259         syscall_getsysinfo(opState);
00260         break;
00261     case syscall_id_osf_setsysinfo:
00262         syscall_setsysinfo(opState);
00263         break;
00264     case syscall_id_getxpid:
00265     case syscall_id_gettid:
00266         syscall_getpid(opState);
00267         break;
00268     //case syscall_id_setuid:
00269     //  syscall_setuid(opState);
00270     //  break;
00271     //case syscall_id_getuid:
00272     //  syscall_getuid(opState);
00273     //  break;
00274     //case syscall_id_setgid:
00275     //  syscall_setgid(opState);
00276     //  break;
00277     case syscall_id_getxgid:        // egid -> a4 (!), gid -> a3, error -> v0 タ
00278         syscall_getegid(opState);
00279     //  break;
00280     //case syscall_id_seteuid:
00281     //  syscall_seteuid(opState);
00282     //  break;
00283     case syscall_id_getxuid:        // euid -> a4 (!), uid -> a3, error -> v0 タ
00284         syscall_geteuid(opState);
00285         break;
00286     //case syscall_id_setegid:
00287     //  syscall_setegid(opState);
00288     //  break;
00289     //case syscall_id_getegid:
00290     //  syscall_getegid(opState);
00291     //  break;
00292     //case syscall_id_setregid:
00293     //  syscall_setregid(opState);
00294     //  break;
00295     //case syscall_id_setreuid:
00296     //  syscall_setreuid(opState);
00297     //  break;
00298     case syscall_id_access:
00299         syscall_access(opState);
00300         break;
00301     case syscall_id_stat:
00302     case syscall_id_stat64:
00303         syscall_stat64(opState);
00304         break;
00305     case syscall_id_lstat:
00306     case syscall_id_lstat64:
00307         syscall_lstat64(opState);
00308         break;
00309     case syscall_id_fstat:
00310     case syscall_id_fstat64:
00311         syscall_fstat64(opState);
00312         break;
00313     case syscall_id_ioctl:
00314         syscall_ioctl(opState);
00315         break;
00316     //case syscall_id_readlink:
00317     //  syscall_readlink(opState);
00318     //  break;
00319     case syscall_id_times:
00320         syscall_times(opState);
00321         break;
00322     case syscall_id_gettimeofday:
00323         syscall_gettimeofday(opState);
00324         break;
00325 
00326     case syscall_id_dup:
00327         syscall_dup(opState);
00328         break;
00329     case syscall_id_truncate:
00330         syscall_truncate(opState);
00331         break;
00332     case syscall_id_ftruncate:
00333         syscall_ftruncate(opState);
00334         break;
00335 
00336     // signal functions
00337     case syscall_id_rt_sigaction:
00338     case syscall_id_osf_sigprocmask:
00339         syscall_ignore(opState);
00340         break;
00341     case syscall_id_kill:
00342         syscall_kill(opState);
00343         break;
00344     case syscall_id_tgkill:
00345         syscall_tgkill(opState);
00346         break;
00347 
00348     // gcc  stack ggp
00349     case syscall_id_getrlimit:
00350         syscall_ignore(opState);
00351         break;
00352     case syscall_id_setrlimit:
00353         syscall_ignore(opState);
00354         break;
00355 
00356     case syscall_id_mkdir:
00357         syscall_mkdir(opState);
00358         break;
00359 
00360     // gcc タsgp
00361     case syscall_id_getrusage:
00362         syscall_ignore(opState);
00363         break;
00364 
00365     case syscall_id_getcwd:
00366         syscall_getcwd(opState);
00367         break;
00368     default:
00369         {
00370             stringstream ss;
00371             ss << "unknown syscall " << GetArg(0) << " called";
00372             THROW_RUNTIME_ERROR(ss.str().c_str());
00373         }
00374     }
00375 #ifdef SYSCALL_DEBUG
00376     if (GetResult(ErrorFlagIndex))
00377         log << " = error " << hex << GetResult(RetValueIndex) << std::endl;
00378     else
00379         log << " = " << hex << GetResult(RetValueIndex) << std::endl;
00380 #endif // #ifdef DEBUG
00381 }
00382 
00383 //
00384 // タ
00385 //
00386 
00387 
00388 namespace {
00389     //struct alpha_stat64
00390     //{
00391     //  u64 alpha_stdev;
00392     //  u64 alpha_stino;        
00393     //  u64 alpha_strdev;
00394     //  s64 alpha_stsize;
00395     //  u64 alpha_stblocks;
00396     //  u32 alpha_stmode;
00397     //  u32 alpha_stuid;
00398     //  u32 alpha_stgid;
00399     //  u32 alpha_stblksize;
00400     //  u32 alpha_stnlink;
00401     //  s32 pad0;
00402     //  s64 alpha_statime;
00403     //  s64 pad1;
00404     //  s64 alpha_stmtime;
00405     //  s64 pad2;
00406     //  s64 alpha_stctime;
00407     //  s64 pad3;
00408     //  s64 unused[3];
00409     //};
00410 
00411     const int ALPHA_CLK_TCK = 1024;
00412     const int ALPHA_MREMAP_MAYMOVE = 1;
00413     const int ALPHA_MAP_NORESERVE = 0x10000;
00414     const int ALPHA_MAP_ANONYMOUS = 0x10;
00415 }
00416 
00417 
00418 // <FIXME>
00419 // http://h50146.www5.hp.com/products/software/oe/tru64unix/manual/v51a_ref/HTML/MAN/MAN2/0120____.HTM
00420 void AlphaLinuxSyscallConv::syscall_getsysinfo(OpEmulationState* opState)
00421 {
00422     u64 kind = GetArg(1);
00423     u64 buffer = GetArg(2);
00424 
00425     switch (kind) {
00426     case 45: // GSI_IEEE_FP_CONTROL
00427     {
00428         EmuMemAccess access( buffer, sizeof(u64), (u64)0x137f );
00429         GetMemorySystem()->WriteMemory( &access );      // write default value
00430         SetResult(true, 0);
00431         break;
00432     }
00433     default:
00434         SetResult(false, EINVAL);
00435         break;
00436     }
00437 }
00438 
00439 // http://h50146.www5.hp.com/products/software/oe/tru64unix/manual/v51a_ref/HTML/MAN/MAN2/0185____.HTM
00440 void AlphaLinuxSyscallConv::syscall_setsysinfo(OpEmulationState* opState)
00441 {
00442     u64 kind = GetArg(1);
00443 //  u64 buffer = GetArg(2);
00444 
00445     switch (kind) {
00446     case 14:    // SSI_IEEE_FP_CONTROL  I[hO(FPOEXe[^X)
00447         SetResult(true, 0);
00448         break;
00449     default:
00450         SetResult(false, EINVAL);
00451         break;
00452     }
00453 }
00454 
00455 //
00456 // conversion
00457 //
00458 
00459 int AlphaLinuxSyscallConv::Get_MAP_ANONYMOUS()
00460 {
00461     return ALPHA_MAP_ANONYMOUS;
00462 }
00463 
00464 int AlphaLinuxSyscallConv::Get_MREMAP_MAYMOVE()
00465 {
00466     return ALPHA_MREMAP_MAYMOVE;
00467 }
00468 
00469 int AlphaLinuxSyscallConv::Get_CLK_TCK()
00470 {
00471     return ALPHA_CLK_TCK;
00472 }
00473 
00474 //void AlphaLinuxSyscallConv::write_stat64(u64 dest, const HostStat &src)
00475 //{
00476 //  static u32 AlphaLinuxSyscallConst_host_st_mode[] =
00477 //  {
00478 //      POSIX_S_IFDIR,
00479 //      POSIX_S_IFCHR,
00480 //      POSIX_S_IFREG,
00481 //      POSIX_S_IFIFO,
00482 //  };
00483 //  static u32 AlphaLinuxSyscallConst_alpha_st_mode[] =
00484 //  {
00485 //      0040000, // _S_IFDIR
00486 //      0020000, // _S_IFCHR
00487 //      0100000, // _S_IFREG
00488 //      0010000, // _S_IFIFO
00489 //  };
00490 //  static int AlphaLinuxSyscallConst_st_mode_size = sizeof(AlphaLinuxSyscallConst_host_st_mode)/sizeof(AlphaLinuxSyscallConst_host_st_mode[0]);
00491 //  SyscallConstConvEnum conv(
00492 //      AlphaLinuxSyscallConst_host_st_mode,
00493 //      AlphaLinuxSyscallConst_alpha_st_mode, 
00494 //      AlphaLinuxSyscallConst_st_mode_size);
00495 //
00496 //  TargetBuffer buf(GetMemorySystem(), dest, sizeof(alpha_stat64));
00497 //  alpha_stat64* a_buf = static_cast<alpha_stat64*>(buf.Get());
00498 //  memset(a_buf, 0, sizeof(alpha_stat64));
00499 //
00500 //  a_buf->alpha_stdev = src.st_dev;
00501 //  a_buf->alpha_stino = src.st_ino;
00502 //  a_buf->alpha_strdev = src.st_rdev;
00503 //  a_buf->alpha_stsize = src.st_size;
00504 //  a_buf->alpha_stuid = src.st_uid;
00505 //  a_buf->alpha_stgid = src.st_gid;
00506 //  a_buf->alpha_stnlink = src.st_nlink;
00507 //  a_buf->alpha_statime = src.st_atime;
00508 //  a_buf->alpha_stmtime = src.st_mtime;
00509 //  a_buf->alpha_stctime = src.st_ctime;
00510 //
00511 //#if defined(HOST_IS_WINDOWS) || defined(HOST_IS_CYGWIN)
00512 //  a_buf->alpha_stmode = conv.TargetToHost(src.st_mode);
00513 //  a_buf->alpha_stblocks = src.st_size;
00514 //  a_buf->alpha_stblksize = 1;
00515 //#else
00516 //  a_buf->alpha_stblocks = src.st_blocks;
00517 //  a_buf->alpha_stmode = src.st_mode;
00518 //  a_buf->alpha_stblksize = src.st_blksize;
00519 //#endif
00520 //}
00521 
00522 
00523 u32 AlphaLinuxSyscallConv::OpenFlagTargetToHost(u32 flag)
00524 {
00525     static u32 AlphaLinuxSyscallConst_host_open_flags[] =
00526     {
00527       POSIX_O_RDONLY, POSIX_O_WRONLY, POSIX_O_RDWR,
00528       POSIX_O_APPEND,
00529       POSIX_O_CREAT,
00530       POSIX_O_EXCL,
00531 //    O_NOCTTY,
00532 //    O_NONBLOCK,
00533 //    O_SYNC,
00534       POSIX_O_TRUNC,
00535     };
00536     static u32 AlphaLinuxSyscallConst_alpha_open_flags[] =
00537     {
00538       00, 01, 02,   // O_RDONLY, O_WRONLY, O_RDWR,
00539       00010,    // O_APPEND
00540       01000,    // O_CREAT
00541       04000,    // O_EXCL
00542 //    010000,   // O_NOCTTY
00543 //    00004,    // O_NONBLOCK
00544 //    040000,   // O_SYNC
00545       02000,    // O_TRUNC
00546     };
00547     static int AlphaLinuxSyscallConst_open_flags_size = sizeof(AlphaLinuxSyscallConst_host_open_flags)/sizeof(AlphaLinuxSyscallConst_host_open_flags[0]);
00548 
00549     SyscallConstConvBitwise conv(
00550         AlphaLinuxSyscallConst_host_open_flags,
00551         AlphaLinuxSyscallConst_alpha_open_flags, 
00552         AlphaLinuxSyscallConst_open_flags_size);
00553 
00554     return conv.TargetToHost(flag);
00555 }
00556 

Onikiri2に対してTue Jun 18 14:34:19 2013に生成されました。  doxygen 1.4.7