00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032 #include <pch.h>
00033
00034 #include "Emu/PPC64Linux/PPC64LinuxSyscallConv.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/PPC64Linux/PPC64LinuxSyscallID.h"
00047
00048 #define SYSCALL_DEBUG
00049
00050 using namespace std;
00051 using namespace Onikiri;
00052 using namespace Onikiri::EmulatorUtility;
00053 using namespace Onikiri::PPC64Linux;
00054 using namespace Onikiri::POSIX;
00055
00056
00057 PPC64LinuxSyscallConv::PPC64LinuxSyscallConv(ProcessState* processState) : Linux64SyscallConv(processState)
00058 {
00059 }
00060
00061 PPC64LinuxSyscallConv::~PPC64LinuxSyscallConv()
00062 {
00063 }
00064
00065 #ifdef SYSCALL_DEBUG
00066 #define SYSCALLNAME(name, argcnt, argtempl) {syscall_id_##name, #name, argcnt, argtempl}
00067
00068 namespace {
00069
00070
00071
00072
00073
00074
00075 static struct {
00076 unsigned int syscallNo;
00077 const char* name;
00078 int argcnt;
00079 const char* argtempl;
00080 } syscallTable[] = {
00081 SYSCALLNAME(exit, 0, ""),
00082 SYSCALLNAME(read, 3, "npn"),
00083 SYSCALLNAME(write, 3, "npn"),
00084 SYSCALLNAME(readv, 3, "npn"),
00085 SYSCALLNAME(writev, 3, "npn"),
00086 SYSCALLNAME(open, 3, "sxx"),
00087 SYSCALLNAME(close, 1, "n"),
00088 SYSCALLNAME(stat, 2, "sp"),
00089 SYSCALLNAME(lstat, 2, "sp"),
00090 SYSCALLNAME(fstat, 2, "np"),
00091
00092
00093
00094 SYSCALLNAME(lseek, 3, "nxn"),
00095 SYSCALLNAME(truncate, 2, "px"),
00096 SYSCALLNAME(ftruncate, 2, "nx"),
00097 SYSCALLNAME(fcntl, 3, "nnp"),
00098 SYSCALLNAME(chdir, 1, "p"),
00099 SYSCALLNAME(fchdir, 1, "n"),
00100 SYSCALLNAME(getcwd, 2, "px"),
00101 SYSCALLNAME(mkdir, 2, "sx"),
00102 SYSCALLNAME(rmdir, 1, "s"),
00103 SYSCALLNAME(readlink, 3, "spx"),
00104 SYSCALLNAME(unlink, 1, "s"),
00105 SYSCALLNAME(link, 2, "ss"),
00106 SYSCALLNAME(rename, 2, "ss"),
00107 SYSCALLNAME(mmap, 6, "pxxxnx"),
00108 SYSCALLNAME(mremap, 4, "pxxx"),
00109 SYSCALLNAME(munmap, 2, "px"),
00110 SYSCALLNAME(mprotect, 3, "pxx"),
00111 SYSCALLNAME(chmod, 2, "sx"),
00112 SYSCALLNAME(ioctl, 3, "xxx"),
00113 SYSCALLNAME(time, 1, "p"),
00114 SYSCALLNAME(times, 1, "p"),
00115 SYSCALLNAME(gettimeofday, 2, "pp"),
00116
00117
00118 SYSCALLNAME(uname, 1, "p"),
00119 SYSCALLNAME(brk, 1, "p"),
00120
00121 SYSCALLNAME(access, 2, "sx"),
00122
00123 SYSCALLNAME(gettid, 0, ""),
00124 SYSCALLNAME(setuid, 1, "x"),
00125 SYSCALLNAME(getuid, 0, ""),
00126
00127 SYSCALLNAME(setgid, 1, "x"),
00128 SYSCALLNAME(getgid, 0, ""),
00129
00130 SYSCALLNAME(geteuid, 0, ""),
00131 SYSCALLNAME(getegid, 0, ""),
00132
00133
00134 SYSCALLNAME(getrusage, 2, "xp"),
00135 SYSCALLNAME(getrlimit, 2, "np"),
00136 SYSCALLNAME(setrlimit, 2, "np"),
00137 SYSCALLNAME(exit_group, 0, ""),
00138 SYSCALLNAME(dup, 1, "n"),
00139
00140 SYSCALLNAME(rt_sigaction, 3, "xxx"),
00141 SYSCALLNAME(rt_sigprocmask, 3, "xxx"),
00142 SYSCALLNAME(kill, 2, "xx"),
00143 SYSCALLNAME(tgkill, 3, "xxx"),
00144 };
00145 #undef SYSCALLNAME
00146
00147 }
00148 #endif // #ifdef SYSCALL_DEBUG
00149
00150
00151 void PPC64LinuxSyscallConv::Execute(OpEmulationState* opState)
00152 {
00153 #ifdef SYSCALL_DEBUG
00154 static std::ofstream log("syscall.log", std::ios_base::out | std::ios_base::trunc);
00155
00156 log << dec << GetArg(0) << " ";
00157 for (size_t i = 0; i < sizeof(syscallTable)/sizeof(syscallTable[0]); i ++) {
00158 if (syscallTable[i].syscallNo == GetArg(0)) {
00159 log << syscallTable[i].name << "(";
00160 int argcnt = syscallTable[i].argcnt;
00161 const char *argtempl = syscallTable[i].argtempl;
00162 for (int j = 1; j <= argcnt; j ++) {
00163 switch (argtempl[j-1]) {
00164 case 's':
00165 {
00166 std::string s = StrCpyToHost( GetMemorySystem(), GetArg(j) );
00167 log << "0x" << hex << GetArg(j) << dec;
00168 log << "=\"" << s << "\"";
00169 }
00170 break;
00171 case 'n':
00172 log << dec << (s64)GetArg(j);
00173 break;
00174 case 'p':
00175 case 'x':
00176 default:
00177 log << "0x" << hex << GetArg(j) << dec;
00178 break;
00179 }
00180 if (j != argcnt)
00181 log << ", ";
00182 }
00183 log << ")";
00184 }
00185 }
00186 log << flush;
00187 #endif // #ifdef SYSCALL_DEBUG
00188
00189 opState->SetTakenPC( opState->GetPC()+4 );
00190 opState->SetTaken(true);
00191
00192 SetResult(false, 0);
00193 switch (GetArg(0)) {
00194 case syscall_id_exit:
00195 case syscall_id_exit_group:
00196 syscall_exit(opState);
00197 break;
00198 case syscall_id_read:
00199 syscall_read(opState);
00200 break;
00201 case syscall_id_write:
00202 syscall_write(opState);
00203 break;
00204 case syscall_id_readv:
00205 syscall_readv(opState);
00206 break;
00207 case syscall_id_writev:
00208 syscall_writev(opState);
00209 break;
00210 case syscall_id_open:
00211 syscall_open(opState);
00212 break;
00213 case syscall_id_close:
00214 syscall_close(opState);
00215 break;
00216
00217 case syscall_id_lseek:
00218 syscall_lseek(opState);
00219 break;
00220 case syscall_id_unlink:
00221 syscall_unlink(opState);
00222 break;
00223 case syscall_id_rename:
00224 syscall_rename(opState);
00225 break;
00226
00227
00228 case syscall_id_mmap:
00229 syscall_mmap(opState);
00230 break;
00231 case syscall_id_mremap:
00232 syscall_mremap(opState);
00233 break;
00234 case syscall_id_munmap:
00235 syscall_munmap(opState);
00236 break;
00237
00238
00239
00240 case syscall_id_uname:
00241 syscall_uname(opState);
00242 break;
00243 case syscall_id_fcntl:
00244 syscall_fcntl(opState);
00245 break;
00246 case syscall_id_brk:
00247 syscall_brk(opState);
00248 break;
00249 case syscall_id_getpid:
00250 case syscall_id_gettid:
00251 syscall_getpid(opState);
00252 break;
00253
00254
00255
00256 case syscall_id_getuid:
00257 syscall_getuid(opState);
00258 break;
00259 case syscall_id_geteuid:
00260 syscall_geteuid(opState);
00261 break;
00262 case syscall_id_getgid:
00263 syscall_getgid(opState);
00264 break;
00265 case syscall_id_getegid:
00266 syscall_getegid(opState);
00267 break;
00268
00269
00270
00271
00272
00273
00274
00275
00276
00277
00278
00279
00280
00281
00282
00283
00284
00285
00286 case syscall_id_stat:
00287
00288 syscall_stat64(opState);
00289 break;
00290 case syscall_id_lstat:
00291
00292 syscall_lstat64(opState);
00293 break;
00294 case syscall_id_fstat:
00295
00296 syscall_fstat64(opState);
00297 break;
00298 case syscall_id_ioctl:
00299 syscall_ioctl(opState);
00300 break;
00301
00302
00303
00304 case syscall_id_time:
00305 syscall_time(opState);
00306 break;
00307 case syscall_id_times:
00308 syscall_times(opState);
00309 break;
00310 case syscall_id_gettimeofday:
00311 syscall_gettimeofday(opState);
00312 break;
00313
00314 case syscall_id_dup:
00315 syscall_dup(opState);
00316 break;
00317 case syscall_id_truncate:
00318 syscall_truncate(opState);
00319 break;
00320 case syscall_id_ftruncate:
00321 syscall_ftruncate(opState);
00322 break;
00323
00324 case syscall_id_kill:
00325 syscall_kill(opState);
00326 break;
00327 case syscall_id_tgkill:
00328 syscall_tgkill(opState);
00329 break;
00330
00331
00332
00333 case syscall_id_rt_sigaction:
00334 case syscall_id_rt_sigprocmask:
00335 syscall_ignore(opState);
00336 break;
00337
00338
00339 case syscall_id_getrlimit:
00340 syscall_ignore(opState);
00341 break;
00342 case syscall_id_setrlimit:
00343 syscall_ignore(opState);
00344 break;
00345
00346
00347
00348
00349
00350
00351 case syscall_id_getrusage:
00352 syscall_ignore(opState);
00353 break;
00354
00355 case syscall_id_getcwd:
00356 syscall_getcwd(opState);
00357 break;
00358 default:
00359 {
00360 stringstream ss;
00361 ss << "unknown syscall " << GetArg(0) << " called";
00362 THROW_RUNTIME_ERROR(ss.str().c_str());
00363 }
00364 }
00365 #ifdef SYSCALL_DEBUG
00366 if (GetResult(ErrorFlagIndex))
00367 log << " = error " << hex << GetResult(RetValueIndex) << std::endl;
00368 else
00369 log << " = " << hex << GetResult(RetValueIndex) << std::endl;
00370 #endif // #ifdef DEBUG
00371 }
00372
00373 namespace {
00374 const int PPC64_CLK_TCK = 100;
00375
00376 const int PPC64_MREMAP_MAYMOVE = 1;
00377 const int PPC64_MAP_NORESERVE = 0x00040;
00378 const int PPC64_MAP_ANONYMOUS = 0x20;
00379 }
00380
00381 int PPC64LinuxSyscallConv::Get_MAP_ANONYMOUS()
00382 {
00383 return PPC64_MAP_ANONYMOUS;
00384 }
00385
00386 int PPC64LinuxSyscallConv::Get_MREMAP_MAYMOVE()
00387 {
00388 return PPC64_MREMAP_MAYMOVE;
00389 }
00390
00391 int PPC64LinuxSyscallConv::Get_CLK_TCK()
00392 {
00393 return PPC64_CLK_TCK;
00394 }
00395
00396 u32 PPC64LinuxSyscallConv::OpenFlagTargetToHost(u32 flag)
00397 {
00398 static u32 host_open_flags[] =
00399 {
00400 POSIX_O_RDONLY, POSIX_O_WRONLY, POSIX_O_RDWR,
00401 POSIX_O_APPEND,
00402 POSIX_O_CREAT,
00403 POSIX_O_EXCL,
00404
00405
00406
00407 POSIX_O_TRUNC,
00408 };
00409
00410 static u32 ppc64_open_flags[] =
00411 {
00412 00, 01, 02,
00413 02000,
00414 00100,
00415 00200,
00416
00417
00418
00419 01000,
00420 };
00421 static int open_flags_size = sizeof(host_open_flags)/sizeof(host_open_flags[0]);
00422
00423 SyscallConstConvBitwise conv(
00424 host_open_flags,
00425 ppc64_open_flags,
00426 open_flags_size);
00427
00428 return conv.TargetToHost(flag);
00429 }