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/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
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
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
00075
00076
00077
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
00132
00133
00134 SYSCALLNAME(getxuid, 0, ""),
00135
00136 SYSCALLNAME(getxgid, 0, ""),
00137
00138
00139
00140
00141
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 }
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
00269
00270
00271
00272
00273
00274
00275
00276
00277 case syscall_id_getxgid:
00278 syscall_getegid(opState);
00279
00280
00281
00282
00283 case syscall_id_getxuid:
00284 syscall_geteuid(opState);
00285 break;
00286
00287
00288
00289
00290
00291
00292
00293
00294
00295
00296
00297
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
00317
00318
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
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
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
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
00390
00391
00392
00393
00394
00395
00396
00397
00398
00399
00400
00401
00402
00403
00404
00405
00406
00407
00408
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
00419
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:
00427 {
00428 EmuMemAccess access( buffer, sizeof(u64), (u64)0x137f );
00429 GetMemorySystem()->WriteMemory( &access );
00430 SetResult(true, 0);
00431 break;
00432 }
00433 default:
00434 SetResult(false, EINVAL);
00435 break;
00436 }
00437 }
00438
00439
00440 void AlphaLinuxSyscallConv::syscall_setsysinfo(OpEmulationState* opState)
00441 {
00442 u64 kind = GetArg(1);
00443
00444
00445 switch (kind) {
00446 case 14:
00447 SetResult(true, 0);
00448 break;
00449 default:
00450 SetResult(false, EINVAL);
00451 break;
00452 }
00453 }
00454
00455
00456
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
00475
00476
00477
00478
00479
00480
00481
00482
00483
00484
00485
00486
00487
00488
00489
00490
00491
00492
00493
00494
00495
00496
00497
00498
00499
00500
00501
00502
00503
00504
00505
00506
00507
00508
00509
00510
00511
00512
00513
00514
00515
00516
00517
00518
00519
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
00532
00533
00534 POSIX_O_TRUNC,
00535 };
00536 static u32 AlphaLinuxSyscallConst_alpha_open_flags[] =
00537 {
00538 00, 01, 02,
00539 00010,
00540 01000,
00541 04000,
00542
00543
00544
00545 02000,
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