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 #include <time.h>
00034
00035 #include "Emu/Utility/System/Syscall/Linux64SyscallConv.h"
00036
00037 #include "Interface/SystemIF.h"
00038 #include "Env/Env.h"
00039 #include "SysDeps/posix.h"
00040 #include "SysDeps/Endian.h"
00041
00042 #include "Emu/Utility/System/ProcessState.h"
00043 #include "Emu/Utility/System/Memory/MemorySystem.h"
00044 #include "Emu/Utility/System/Memory/MemoryUtility.h"
00045 #include "Emu/Utility/System/VirtualSystem.h"
00046 #include "Emu/Utility/System/Syscall/SyscallConstConv.h"
00047 #include "Emu/Utility/OpEmulationState.h"
00048
00049
00050
00051 using namespace std;
00052 using namespace boost;
00053 using namespace Onikiri;
00054 using namespace Onikiri::EmulatorUtility;
00055 using namespace Onikiri::POSIX;
00056
00057
00058
00059
00060 Linux64SyscallConv::Linux64SyscallConv(ProcessState* processState)
00061 : m_processState(processState)
00062 {
00063 m_args.resize(MaxArgCount);
00064 m_results.resize(MaxResultCount);
00065 }
00066
00067 Linux64SyscallConv::~Linux64SyscallConv()
00068 {
00069 }
00070
00071 void Linux64SyscallConv::SetArg(int index, u64 value)
00072 {
00073 m_args.at(index) = value;
00074 }
00075
00076 u64 Linux64SyscallConv::GetResult(int index)
00077 {
00078 return m_results.at(index);
00079 }
00080
00081 void Linux64SyscallConv::SetResult(bool success, u64 result)
00082 {
00083 m_results[RetValueIndex] = result;
00084 m_results[ErrorFlagIndex] = success ? 0 : 1;
00085 }
00086
00087 void Linux64SyscallConv::SetSystem(SystemIF* system)
00088 {
00089 m_simulatorSystem = system;
00090 }
00091
00092
00093
00094
00095
00096
00097
00098 namespace {
00099 struct linux64_stat64
00100 {
00101 u64 linux64_stdev;
00102 u64 linux64_stino;
00103 u64 linux64_strdev;
00104 s64 linux64_stsize;
00105 u64 linux64_stblocks;
00106 u32 linux64_stmode;
00107 u32 linux64_stuid;
00108 u32 linux64_stgid;
00109 u32 linux64_stblksize;
00110 u32 linux64_stnlink;
00111 s32 pad0;
00112 s64 linux64_statime;
00113 s64 pad1;
00114 s64 linux64_stmtime;
00115 s64 pad2;
00116 s64 linux64_stctime;
00117 s64 pad3;
00118 s64 unused[3];
00119 };
00120
00121 struct linux64_iovec
00122 {
00123 u64 linux64_iov_base;
00124 u64 linux64_iov_len;
00125 };
00126
00127 struct linux64_tms
00128 {
00129 s64 linux64_tms_utime;
00130 s64 linux64_tms_stime;
00131 s64 linux64_tms_cutime;
00132 s64 linux64_tms_cstime;
00133 };
00134
00135 struct linux64_timeval {
00136 s64 linux64_tv_sec;
00137 s64 linux64_tv_usec;
00138 };
00139
00140 typedef s64 linux64_time_t;
00141
00142
00143 const int LINUX_F_GETFD = 1;
00144 const int LINUX_F_SETFD = 2;
00145
00146 const int LINUX_F_OK = 0;
00147 const int LINUX_X_OK = 0;
00148 const int LINUX_W_OK = 2;
00149 const int LINUX_R_OK = 4;
00150
00151 const int LINUX_SEEK_SET = 0;
00152 const int LINUX_SEEK_CUR = 1;
00153 const int LINUX_SEEK_END = 2;
00154 }
00155
00156
00157
00158 void Linux64SyscallConv::syscall_ignore(OpEmulationState* opState)
00159 {
00160 m_results[RetValueIndex] = (u64)0;
00161 m_results[ErrorFlagIndex] = (u64)0;
00162 }
00163
00164 void Linux64SyscallConv::syscall_exit(OpEmulationState* opState)
00165 {
00166 opState->SetTakenPC(0);
00167 opState->SetTaken(true);
00168
00169 m_simulatorSystem->NotifyProcessTermination(opState->GetPID());
00170 }
00171
00172 void Linux64SyscallConv::syscall_getuid(OpEmulationState* opState)
00173 {
00174 SetResult(true, (u64)posix_getuid());
00175 }
00176
00177 void Linux64SyscallConv::syscall_geteuid(OpEmulationState* opState)
00178 {
00179 SetResult(true, (u64)posix_geteuid());
00180 }
00181
00182 void Linux64SyscallConv::syscall_getgid(OpEmulationState* opState)
00183 {
00184 SetResult(true, (u64)posix_getgid());
00185 }
00186
00187 void Linux64SyscallConv::syscall_getegid(OpEmulationState* opState)
00188 {
00189 SetResult(true, (u64)posix_getegid());
00190 }
00191
00192 void Linux64SyscallConv::syscall_brk(OpEmulationState* opState)
00193 {
00194 if (m_args[1] == 0) {
00195 SetResult(true, GetMemorySystem()->Brk(0));
00196 return;
00197 }
00198
00199 if (GetMemorySystem()->Brk(m_args[1]) == (u64)-1) {
00200 SetResult(false, ENOMEM);
00201 }
00202 else {
00203
00204 SetResult(true, GetMemorySystem()->Brk(0));
00205 }
00206 }
00207
00208 void Linux64SyscallConv::syscall_mmap(OpEmulationState* opState)
00209 {
00210 u64 result;
00211 if (!(m_args[4] & Get_MAP_ANONYMOUS())) {
00212 result = (u64)-1;
00213 }
00214 else {
00215 result = GetMemorySystem()->MMap(m_args[1], m_args[2]);
00216 }
00217
00218 if (result == (u64)-1)
00219 SetResult(false, ENOMEM);
00220 else
00221 SetResult(true, result);
00222 }
00223 void Linux64SyscallConv::syscall_mremap(OpEmulationState* opState)
00224 {
00225 u64 result = GetMemorySystem()->MRemap(m_args[1], m_args[2], m_args[3], (m_args[4] & Get_MREMAP_MAYMOVE()) != 0);
00226 if (result == (u64)-1)
00227 SetResult(false, ENOMEM);
00228 else
00229 SetResult(true, result);
00230 }
00231 void Linux64SyscallConv::syscall_munmap(OpEmulationState* opState)
00232 {
00233 int result = GetMemorySystem()->MUnmap(m_args[1], m_args[2]);
00234 if (result == -1)
00235 SetResult(false, EINVAL);
00236 else
00237 SetResult(true, (u64)result);
00238 }
00239 void Linux64SyscallConv::syscall_mprotect(OpEmulationState* opState)
00240 {
00241 SetResult(true, (u64)0);
00242 }
00243
00244 void Linux64SyscallConv::syscall_uname(OpEmulationState* opState)
00245 {
00246
00247 struct utsname_linux
00248 {
00249 char sysname[65];
00250 char nodename[65];
00251 char release[65];
00252 char version[65];
00253 char machine[65];
00254 } utsname;
00255
00256 memset(&utsname, 0, sizeof(utsname));
00257 strcpy(utsname.release, "2.6.23");
00258
00259 GetMemorySystem()->MemCopyToTarget(m_args[1], &utsname, sizeof(utsname));
00260
00261 SetResult(true, 0);
00262 }
00263
00264
00265
00266 void Linux64SyscallConv::syscall_getpid(OpEmulationState* opState)
00267 {
00268 SetResult(true, (u64)posix_getpid());
00269 }
00270
00271 void Linux64SyscallConv::syscall_kill(OpEmulationState* opState)
00272 {
00273 kill_helper(opState, (int)m_args[1], (int)m_args[2]);
00274 }
00275
00276 void Linux64SyscallConv::syscall_tgkill(OpEmulationState* opState)
00277 {
00278 ASSERT(m_args[1] == m_args[2]);
00279 kill_helper(opState, (int)m_args[1], (int)m_args[3]);
00280 }
00281
00282 void Linux64SyscallConv::kill_helper(OpEmulationState* opState, int arg_pid, int arg_sig)
00283 {
00284 if (arg_pid == posix_getpid()) {
00285 if (arg_sig == 6)
00286 g_env.Print("target program aborted.\n");
00287 else
00288 g_env.Print("signaling with kill not implemented yet.\n");
00289 }
00290 else {
00291 g_env.Print("target program attempted to kill another process.\n");
00292 }
00293
00294 syscall_exit(opState);
00295 }
00296
00297 void Linux64SyscallConv::syscall_getcwd(OpEmulationState* opState)
00298 {
00299 int bufSize = (int)m_args[2];
00300
00301 TargetBuffer buf(GetMemorySystem(), m_args[1], bufSize+1);
00302 void *result = GetVirtualSystem()->GetCWD(static_cast<char*>(buf.Get()), bufSize);
00303 if (result == NULL) {
00304 SetResult(false, GetVirtualSystem()->GetErrno());
00305 }
00306 else {
00307 SetResult(true, m_args[1]);
00308 }
00309 }
00310
00311 void Linux64SyscallConv::syscall_open(OpEmulationState* opState)
00312 {
00313 std::string fileName = StrCpyToHost( GetMemorySystem(), m_args[1] );
00314 int result = GetVirtualSystem()->Open(
00315 fileName.c_str(),
00316 (int)OpenFlagTargetToHost( static_cast<u32>(m_args[2]) )
00317 );
00318
00319 if (result == -1)
00320 SetResult(false, GetVirtualSystem()->GetErrno());
00321 else
00322 SetResult(true, result);
00323 }
00324
00325 void Linux64SyscallConv::syscall_close(OpEmulationState* opState)
00326 {
00327 int result = GetVirtualSystem()->Close((int)m_args[1]);
00328 if (result == -1)
00329 SetResult(false, GetVirtualSystem()->GetErrno());
00330 else
00331 SetResult(true, result);
00332 }
00333
00334 void Linux64SyscallConv::syscall_dup(OpEmulationState* opState)
00335 {
00336 int result = GetVirtualSystem()->Dup((int)m_args[1]);
00337 if (result == -1)
00338 SetResult(false, GetVirtualSystem()->GetErrno());
00339 else
00340 SetResult(true, result);
00341 }
00342
00343 void Linux64SyscallConv::syscall_read(OpEmulationState* opState)
00344 {
00345 unsigned int bufSize = (unsigned int)m_args[3];
00346 TargetBuffer buf(GetMemorySystem(), m_args[2], bufSize);
00347 int result = GetVirtualSystem()->Read((int)m_args[1], buf.Get(), bufSize);
00348 if (result == -1) {
00349 SetResult(false, GetVirtualSystem()->GetErrno());
00350 }
00351 else {
00352 m_simulatorSystem->NotifySyscallReadFileToMemory(Addr(opState->GetPID(), opState->GetTID(), m_args[2]), bufSize);
00353 SetResult(true, result);
00354 }
00355 }
00356
00357 void Linux64SyscallConv::syscall_write(OpEmulationState* opState)
00358 {
00359 unsigned int bufSize = (unsigned int)m_args[3];
00360 TargetBuffer buf(GetMemorySystem(), m_args[2], bufSize);
00361 int result = GetVirtualSystem()->Write((int)m_args[1], buf.Get(), bufSize);
00362 if (result == -1) {
00363 SetResult(false, GetVirtualSystem()->GetErrno());
00364 }
00365 else {
00366 m_simulatorSystem->NotifySyscallWriteFileFromMemory(Addr(opState->GetPID(), opState->GetTID(), m_args[2]), bufSize);
00367 SetResult(true, result);
00368 }
00369 }
00370
00371
00372 void Linux64SyscallConv::syscall_readv(OpEmulationState* opState)
00373 {
00374 int iovcnt = (int)m_args[3];
00375 s64 result = 0;
00376 const TargetBuffer iovecBuf(GetMemorySystem(), m_args[2], iovcnt*sizeof(linux64_iovec), true);
00377 const linux64_iovec* iovec = static_cast<const linux64_iovec*>(iovecBuf.Get());
00378
00379 for (int i = 0; i < iovcnt; i ++) {
00380 u64 iov_base = EndianSpecifiedToHost(iovec->linux64_iov_base, GetMemorySystem()->IsBigEndian());
00381 u64 iov_len = EndianSpecifiedToHost(iovec->linux64_iov_len, GetMemorySystem()->IsBigEndian());
00382
00383 TargetBuffer buf(GetMemorySystem(), iov_base, (size_t)iov_len);
00384 int bytesRead = GetVirtualSystem()->Read((int)m_args[1], buf.Get(), (unsigned int)iov_len);
00385
00386 if (result == -1 || bytesRead == -1 || (u64)bytesRead != iov_len) {
00387 SetResult(false, GetVirtualSystem()->GetErrno());
00388 result = -1;
00389 break;
00390 }
00391 else {
00392 m_simulatorSystem->NotifySyscallReadFileToMemory(Addr(opState->GetPID(), opState->GetTID(), iov_base), iov_len);
00393 result += iov_len;
00394 }
00395 iovec++;
00396 }
00397 SetResult(true, result);
00398 }
00399
00400 void Linux64SyscallConv::syscall_writev(OpEmulationState* opState)
00401 {
00402 int iovcnt = (int)m_args[3];
00403 s64 result = 0;
00404 const TargetBuffer iovecBuf(GetMemorySystem(), m_args[2], iovcnt*sizeof(linux64_iovec), true);
00405 const linux64_iovec* iovec = static_cast<const linux64_iovec*>(iovecBuf.Get());
00406
00407 for (int i = 0; i < iovcnt; i ++) {
00408 u64 iov_base = EndianSpecifiedToHost(iovec->linux64_iov_base, GetMemorySystem()->IsBigEndian());
00409 u64 iov_len = EndianSpecifiedToHost(iovec->linux64_iov_len, GetMemorySystem()->IsBigEndian());
00410
00411 TargetBuffer buf(GetMemorySystem(), iov_base, (size_t)iov_len);
00412 int bytesWritten = GetVirtualSystem()->Write((int)m_args[1], buf.Get(), (unsigned int)iov_len);
00413
00414 if (result == -1 || bytesWritten == -1 || (u64)bytesWritten != iov_len) {
00415 SetResult(false, GetVirtualSystem()->GetErrno());
00416 result = -1;
00417 break;
00418 }
00419 else {
00420 m_simulatorSystem->NotifySyscallWriteFileFromMemory(Addr(opState->GetPID(), opState->GetTID(), iov_base), iov_len);
00421 result += iov_len;
00422 }
00423 iovec++;
00424 }
00425 SetResult(true, result);
00426 }
00427
00428 void Linux64SyscallConv::syscall_lseek(OpEmulationState* opState)
00429 {
00430 s64 result = GetVirtualSystem()->LSeek((int)m_args[1], m_args[2], (int)SeekWhenceTargetToHost((u32)m_args[3]));
00431 if (result == -1)
00432 SetResult(false, GetVirtualSystem()->GetErrno());
00433 else
00434 SetResult(true, (u64)result);
00435 }
00436
00437 void Linux64SyscallConv::syscall_fstat64(OpEmulationState* opState)
00438 {
00439 HostStat st;
00440 int result = GetVirtualSystem()->FStat((int)m_args[1], &st);
00441 if (result == -1) {
00442 SetResult(false, GetVirtualSystem()->GetErrno());
00443 }
00444 else {
00445 #ifdef HOST_IS_WINDOWS
00446
00447
00448
00449
00450
00451
00452
00453
00454
00455
00456 if(GetVirtualSystem()->GetDelayUnlinker()->GetMapPath((int)m_args[1]) == "HostIO"){
00457 st.st_rdev = 0x8801;
00458 }
00459 #endif
00460 write_stat64((u64)m_args[2], st);
00461 SetResult(true, result);
00462 }
00463 }
00464
00465 void Linux64SyscallConv::syscall_stat64(OpEmulationState* opState)
00466 {
00467 HostStat st;
00468 string path = StrCpyToHost( GetMemorySystem(), m_args[1] );
00469 int result = GetVirtualSystem()->Stat(path.c_str(), &st);
00470 if (result == -1) {
00471 SetResult(false, GetVirtualSystem()->GetErrno());
00472 }
00473 else {
00474 write_stat64((u64)m_args[2], st);
00475 SetResult(true, result);
00476 }
00477 }
00478
00479 void Linux64SyscallConv::syscall_lstat64(OpEmulationState* opState)
00480 {
00481 HostStat st;
00482 string path = StrCpyToHost( GetMemorySystem(), m_args[1] );
00483 int result = GetVirtualSystem()->LStat(path.c_str(), &st);
00484 if (result == -1) {
00485 SetResult(false, GetVirtualSystem()->GetErrno());
00486 }
00487 else {
00488 write_stat64((u64)m_args[2], st);
00489 SetResult(true, result);
00490 }
00491 }
00492
00493 void Linux64SyscallConv::syscall_fcntl(OpEmulationState* opState)
00494 {
00495 int cmd = (int)m_args[2];
00496 switch (cmd) {
00497 case LINUX_F_GETFD:
00498 case LINUX_F_SETFD:
00499 SetResult(true, 0);
00500 break;
00501 default:
00502 THROW_RUNTIME_ERROR("syscall_fcntl : unknown cmd");
00503 }
00504 }
00505
00506 void Linux64SyscallConv::syscall_mkdir(OpEmulationState* opState)
00507 {
00508 string path = StrCpyToHost( GetMemorySystem(), m_args[1] );
00509 int result = GetVirtualSystem()->MkDir(path.c_str(), (int)m_args[2]);
00510 if (result == -1) {
00511 SetResult(false, GetVirtualSystem()->GetErrno());
00512 }
00513 else {
00514 SetResult(true, result);
00515 }
00516 }
00517
00518 void Linux64SyscallConv::syscall_access(OpEmulationState* opState)
00519 {
00520 string path = StrCpyToHost( GetMemorySystem(), m_args[1] );
00521 int result = GetVirtualSystem()->Access( path.c_str(), (int)AccessModeTargetToHost((u32)m_args[2]) );
00522 if (result == -1)
00523 SetResult(false, GetVirtualSystem()->GetErrno());
00524 else
00525 SetResult(true, result);
00526 }
00527
00528 void Linux64SyscallConv::syscall_unlink(OpEmulationState* opState)
00529 {
00530 string path = StrCpyToHost( GetMemorySystem(), m_args[1] );
00531 int result = GetVirtualSystem()->Unlink( path.c_str() );
00532 if (result == -1)
00533 SetResult(false, GetVirtualSystem()->GetErrno());
00534 else
00535 SetResult(true, result);
00536 }
00537
00538 void Linux64SyscallConv::syscall_rename(OpEmulationState* opState)
00539 {
00540 string oldpath = StrCpyToHost( GetMemorySystem(), m_args[1] );
00541 string newpath = StrCpyToHost( GetMemorySystem(), m_args[2] );
00542
00543 int result = GetVirtualSystem()->Rename( oldpath.c_str(), newpath.c_str() );
00544 if (result == -1)
00545 SetResult(false, GetVirtualSystem()->GetErrno());
00546 else
00547 SetResult(true, result);
00548 }
00549
00550 void Linux64SyscallConv::syscall_truncate(OpEmulationState* opState)
00551 {
00552 string path = StrCpyToHost( GetMemorySystem(), m_args[1] );
00553 int result = GetVirtualSystem()->Truncate( path.c_str(), (s64)m_args[2] );
00554 if (result == -1)
00555 SetResult(false, GetVirtualSystem()->GetErrno());
00556 else
00557 SetResult(true, result);
00558 }
00559
00560 void Linux64SyscallConv::syscall_ftruncate(OpEmulationState* opState)
00561 {
00562 int result = GetVirtualSystem()->FTruncate( (int)m_args[1], (s64)m_args[2] );
00563 if (result == -1)
00564 SetResult(false, GetVirtualSystem()->GetErrno());
00565 else
00566 SetResult(true, result);
00567 }
00568
00569 void Linux64SyscallConv::syscall_time(OpEmulationState* opState)
00570 {
00571 s64 result = GetVirtualSystem()->GetTime();
00572 if (m_args[1] != 0) {
00573 TargetBuffer buf(GetMemorySystem(), m_args[1], sizeof(linux64_time_t));
00574 linux64_time_t* ptime = static_cast<linux64_time_t*>(buf.Get());
00575 *ptime = EndianHostToSpecified(result, GetMemorySystem()->IsBigEndian());
00576 }
00577 SetResult(true, result);
00578 }
00579
00580 void Linux64SyscallConv::syscall_times(OpEmulationState* opState)
00581 {
00582 TargetBuffer buf(GetMemorySystem(), m_args[1], sizeof(linux64_tms));
00583 linux64_tms* tms_buf = static_cast<linux64_tms*>(buf.Get());
00584
00585 s64 clk = GetVirtualSystem()->GetClock();
00586 u64 result = (u64)((double)clk / CLOCKS_PER_SEC * Get_CLK_TCK());
00587 tms_buf->linux64_tms_utime = EndianHostToSpecified(result, GetMemorySystem()->IsBigEndian());
00588 tms_buf->linux64_tms_stime = 0;
00589 tms_buf->linux64_tms_cutime = 0;
00590 tms_buf->linux64_tms_cstime = 0;
00591
00592 SetResult(true, result);
00593 }
00594
00595 void Linux64SyscallConv::syscall_gettimeofday(OpEmulationState* opState)
00596 {
00597 if (m_args[2] != 0) {
00598
00599 SetResult(false, EINVAL);
00600 return;
00601 }
00602 TargetBuffer buf(GetMemorySystem(), m_args[1], sizeof(linux64_timeval));
00603 linux64_timeval* tv_buf = static_cast<linux64_timeval*>(buf.Get());
00604
00605 s64 t = GetVirtualSystem()->GetTime();
00606 tv_buf->linux64_tv_sec = EndianHostToSpecified((u64)t, GetMemorySystem()->IsBigEndian());
00607 tv_buf->linux64_tv_usec = EndianHostToSpecified((u64)t * 1000 * 1000, GetMemorySystem()->IsBigEndian());
00608
00609 SetResult(true, 0);
00610 }
00611
00612 void Linux64SyscallConv::syscall_ioctl(OpEmulationState* opState)
00613 {
00614 const int LINUX_TCGETS = 0x402c7413;
00615
00616
00617
00618 if ((int)m_args[2] == LINUX_TCGETS) {
00619 const int ERRNO_ENOTTY = 25;
00620
00621
00622 if (false) {
00623 SetResult(true, 0);
00624 }
00625 else {
00626 SetResult(false, ERRNO_ENOTTY);
00627 }
00628 }
00629 else {
00630 SetResult(false, EINVAL);
00631 }
00632 }
00633
00634 u32 Linux64SyscallConv::SeekWhenceTargetToHost(u32 flag)
00635 {
00636 static u32 host_whence[] =
00637 {
00638 POSIX_SEEK_SET,
00639 POSIX_SEEK_CUR,
00640 POSIX_SEEK_END
00641 };
00642 static u32 linux_whence[] =
00643 {
00644 LINUX_SEEK_SET,
00645 LINUX_SEEK_CUR,
00646 LINUX_SEEK_END
00647 };
00648 static int whence_size = sizeof(host_whence)/sizeof(host_whence[0]);
00649 SyscallConstConvEnum conv(
00650 host_whence,
00651 linux_whence,
00652 whence_size);
00653
00654 return conv.TargetToHost(flag);
00655 }
00656
00657
00658 u32 Linux64SyscallConv::AccessModeTargetToHost(u32 flag)
00659 {
00660 static u32 host_access_mode[] =
00661 {
00662 POSIX_F_OK,
00663 POSIX_X_OK,
00664 POSIX_W_OK,
00665 POSIX_R_OK
00666 };
00667 static u32 linux_access_mode[] =
00668 {
00669 LINUX_F_OK,
00670 LINUX_X_OK,
00671 LINUX_W_OK,
00672 LINUX_R_OK
00673 };
00674 static int access_mode_size = sizeof(host_access_mode)/sizeof(host_access_mode[0]);
00675 SyscallConstConvBitwise conv(
00676 host_access_mode,
00677 linux_access_mode,
00678 access_mode_size);
00679
00680 return conv.TargetToHost(flag);
00681 }
00682
00683
00684 void Linux64SyscallConv::write_stat64(u64 dest, const HostStat &src)
00685 {
00686 static u32 host_st_mode[] =
00687 {
00688 POSIX_S_IFDIR,
00689 POSIX_S_IFCHR,
00690 POSIX_S_IFREG,
00691 POSIX_S_IFIFO,
00692 };
00693 static u32 linux64_st_mode[] =
00694 {
00695 0040000,
00696 0020000,
00697 0100000,
00698 0010000,
00699 };
00700 static int st_mode_size = sizeof(host_st_mode)/sizeof(host_st_mode[0]);
00701 SyscallConstConvBitwise conv(
00702 host_st_mode,
00703 linux64_st_mode,
00704 st_mode_size);
00705
00706 TargetBuffer buf(GetMemorySystem(), dest, sizeof(linux64_stat64));
00707 linux64_stat64* t_buf = static_cast<linux64_stat64*>(buf.Get());
00708 memset(t_buf, 0, sizeof(linux64_stat64));
00709
00710 t_buf->linux64_stdev = src.st_dev;
00711 t_buf->linux64_stino = src.st_ino;
00712 t_buf->linux64_strdev = src.st_rdev;
00713 t_buf->linux64_stsize = src.st_size;
00714 t_buf->linux64_stuid = src.st_uid;
00715 t_buf->linux64_stgid = src.st_gid;
00716 t_buf->linux64_stnlink = src.st_nlink;
00717 t_buf->linux64_statime = src.st_atime;
00718 t_buf->linux64_stmtime = src.st_mtime;
00719 t_buf->linux64_stctime = src.st_ctime;
00720
00721
00722
00723
00724
00725
00726 #if defined(HOST_IS_WINDOWS) || defined(HOST_IS_CYGWIN)
00727 static const int BLOCK_UNIT = 512*8;
00728 t_buf->linux64_stmode = conv.HostToTarget(src.st_mode);
00729 t_buf->linux64_stblocks = (src.st_size+BLOCK_UNIT-1)/BLOCK_UNIT*8;
00730 t_buf->linux64_stblksize = 32768;
00731 #else
00732 t_buf->linux64_stblocks = src.st_blocks;
00733 t_buf->linux64_stmode = src.st_mode;
00734 t_buf->linux64_stblksize = src.st_blksize;
00735 #endif
00736
00737
00738 bool bigEndian = GetMemorySystem()->IsBigEndian();
00739 EndianHostToSpecifiedInPlace(t_buf->linux64_stdev, bigEndian);
00740 EndianHostToSpecifiedInPlace(t_buf->linux64_stino, bigEndian);
00741 EndianHostToSpecifiedInPlace(t_buf->linux64_strdev, bigEndian);
00742 EndianHostToSpecifiedInPlace(t_buf->linux64_stsize, bigEndian);
00743 EndianHostToSpecifiedInPlace(t_buf->linux64_stuid, bigEndian);
00744 EndianHostToSpecifiedInPlace(t_buf->linux64_stgid, bigEndian);
00745 EndianHostToSpecifiedInPlace(t_buf->linux64_stnlink, bigEndian);
00746 EndianHostToSpecifiedInPlace(t_buf->linux64_statime, bigEndian);
00747 EndianHostToSpecifiedInPlace(t_buf->linux64_stmtime, bigEndian);
00748 EndianHostToSpecifiedInPlace(t_buf->linux64_stctime, bigEndian);
00749 EndianHostToSpecifiedInPlace(t_buf->linux64_stmode, bigEndian);
00750 EndianHostToSpecifiedInPlace(t_buf->linux64_stblocks, bigEndian);
00751 EndianHostToSpecifiedInPlace(t_buf->linux64_stblksize, bigEndian);
00752 }
00753