@@ -28,115 +28,126 @@ tags: LinuxSyscalls|syscalls-x86-64
2828#include < unistd.h>
2929
3030namespace FEX ::HLE::x64 {
31- void RegisterFD (FEX::HLE::SyscallHandler* Handler) {
32- REGISTER_SYSCALL_IMPL_X64 (
33- select, [](FEXCore::Core::CpuStateFrame* Frame, int nfds, fd_set* readfds, fd_set* writefds, fd_set* exceptfds, struct timeval * timeout) -> uint64_t {
34- // /< All FD arrays need to be writable
35- FaultSafeUserMemAccess::VerifyIsWritableOrNull (readfds, sizeof (uint64_t ) * nfds);
36- FaultSafeUserMemAccess::VerifyIsWritableOrNull (writefds, sizeof (uint64_t ) * nfds);
37- FaultSafeUserMemAccess::VerifyIsWritableOrNull (exceptfds, sizeof (uint64_t ) * nfds);
38- FaultSafeUserMemAccess::VerifyIsReadableOrNull (timeout, sizeof (*timeout));
39- // /< timeout doesn't actually need to be writable, this is a quirk of glibc. Kernel just doesn't update timeout if not possible.
40- FaultSafeUserMemAccess::VerifyIsWritableOrNull (timeout, sizeof (*timeout));
41- uint64_t Result = ::select (nfds, readfds, writefds, exceptfds, timeout);
42- SYSCALL_ERRNO ();
43- });
44-
45- REGISTER_SYSCALL_IMPL_X64 (fcntl, [](FEXCore::Core::CpuStateFrame* Frame, int fd, int cmd, uint64_t arg) -> uint64_t {
46- uint64_t Result {};
47- switch (cmd) {
48- case F_GETFL:
49- Result = ::fcntl (fd, cmd, arg);
50- if (Result != -1 ) {
51- Result = FEX::HLE::RemapToX86Flags (Result);
52- }
53- break ;
54- case F_SETFL: Result = ::fcntl (fd, cmd, FEX::HLE::RemapFromX86Flags (arg)); break ;
55- default : Result = ::fcntl (fd, cmd, arg); break ;
56- }
57- SYSCALL_ERRNO ();
58- });
59-
60- REGISTER_SYSCALL_IMPL_X64 (
61- futimesat, [](FEXCore::Core::CpuStateFrame* Frame, int dirfd, const char * pathname, const struct timeval times[2 ]) -> uint64_t {
62- return FEX::HLE::futimesat_compat<timeval>(dirfd, pathname, times);
63- });
64-
65- REGISTER_SYSCALL_IMPL_X64 (stat, [](FEXCore::Core::CpuStateFrame* Frame, const char * pathname, FEX::HLE::x64::guest_stat* buf) -> uint64_t {
66- FaultSafeUserMemAccess::VerifyIsStringReadableMaxSize (pathname, PATH_MAX);
67- FaultSafeUserMemAccess::VerifyIsWritable (buf, sizeof (*buf));
68- struct stat host_stat;
69- uint64_t Result = FEX::HLE::_SyscallHandler->FM .Stat (pathname, &host_stat);
70- if (Result != -1 ) {
71- *buf = host_stat;
72- }
73- SYSCALL_ERRNO ();
74- });
7531
76- REGISTER_SYSCALL_IMPL_X64 (fstat, [](FEXCore::Core::CpuStateFrame* Frame, int fd, FEX::HLE::x64::guest_stat* buf) -> uint64_t {
77- FaultSafeUserMemAccess::VerifyIsWritable (buf, sizeof (*buf));
78- struct stat host_stat;
79- uint64_t Result = ::fstat (fd, &host_stat);
80- if (Result != -1 ) {
81- *buf = host_stat;
82- }
83- SYSCALL_ERRNO ();
84- });
85-
86- REGISTER_SYSCALL_IMPL_X64 (lstat, [](FEXCore::Core::CpuStateFrame* Frame, const char * path, FEX::HLE::x64::guest_stat* buf) -> uint64_t {
87- FaultSafeUserMemAccess::VerifyIsStringReadableMaxSize (path, PATH_MAX);
88- FaultSafeUserMemAccess::VerifyIsWritable (buf, sizeof (*buf));
89- struct stat host_stat;
90- uint64_t Result = FEX::HLE::_SyscallHandler->FM .Lstat (path, &host_stat);
32+ auto select (FEXCore::Core::CpuStateFrame* Frame, int nfds, fd_set* readfds, fd_set* writefds, fd_set* exceptfds, struct timeval * timeout)
33+ -> uint64_t {
34+ // /< All FD arrays need to be writable
35+ FaultSafeUserMemAccess::VerifyIsWritableOrNull (readfds, sizeof (uint64_t ) * nfds);
36+ FaultSafeUserMemAccess::VerifyIsWritableOrNull (writefds, sizeof (uint64_t ) * nfds);
37+ FaultSafeUserMemAccess::VerifyIsWritableOrNull (exceptfds, sizeof (uint64_t ) * nfds);
38+ FaultSafeUserMemAccess::VerifyIsReadableOrNull (timeout, sizeof (*timeout));
39+ // /< timeout doesn't actually need to be writable, this is a quirk of glibc. Kernel just doesn't update timeout if not possible.
40+ FaultSafeUserMemAccess::VerifyIsWritableOrNull (timeout, sizeof (*timeout));
41+ uint64_t Result = ::select (nfds, readfds, writefds, exceptfds, timeout);
42+ SYSCALL_ERRNO ();
43+ }
44+
45+ auto fcntl (FEXCore::Core::CpuStateFrame* Frame, int fd, int cmd, uint64_t arg) -> uint64_t {
46+ uint64_t Result {};
47+ switch (cmd) {
48+ case F_GETFL:
49+ Result = ::fcntl (fd, cmd, arg);
9150 if (Result != -1 ) {
92- *buf = host_stat ;
51+ Result = FEX::HLE::RemapToX86Flags (Result) ;
9352 }
94- SYSCALL_ERRNO ();
95- });
96-
97- REGISTER_SYSCALL_IMPL_X64 (
98- newfstatat, [](FEXCore::Core::CpuStateFrame* Frame, int dirfd, const char * pathname, FEX::HLE::x64::guest_stat* buf, int flag) -> uint64_t {
99- FaultSafeUserMemAccess::VerifyIsStringReadableMaxSize (pathname, PATH_MAX);
100- FaultSafeUserMemAccess::VerifyIsWritable (buf, sizeof (*buf));
101- struct stat host_stat;
102- uint64_t Result = FEX::HLE::_SyscallHandler->FM .NewFSStatAt (dirfd, pathname, &host_stat, flag);
103- if (Result != -1 ) {
104- *buf = host_stat;
105- }
106- SYSCALL_ERRNO ();
107- });
53+ break ;
54+ case F_SETFL: Result = ::fcntl (fd, cmd, FEX::HLE::RemapFromX86Flags (arg)); break ;
55+ default : Result = ::fcntl (fd, cmd, arg); break ;
56+ }
57+ SYSCALL_ERRNO ();
58+ }
10859
109- REGISTER_SYSCALL_IMPL_X64 (getdents, []( FEXCore::Core::CpuStateFrame* Frame, int fd, void * dirp, uint32_t count ) -> uint64_t {
110- return GetDentsEmulation< false >(fd, reinterpret_cast < FEX::HLE::x64::linux_dirent*>(dirp), count );
111- });
60+ auto futimesat ( FEXCore::Core::CpuStateFrame* Frame, int dirfd, const char * pathname, const struct timeval times[ 2 ] ) -> uint64_t {
61+ return FEX::HLE::futimesat_compat<timeval>(dirfd, pathname, times );
62+ }
11263
113- REGISTER_SYSCALL_IMPL_X64 (getdents64, [](FEXCore::Core::CpuStateFrame* Frame, int fd, void * dirp, uint32_t count) -> uint64_t {
114- uint64_t Result = ::syscall (SYSCALL_DEF (getdents64), static_cast <uint64_t >(fd), dirp, static_cast <uint64_t >(count));
115- if (Result != -1 ) {
116- // Check for and hide the RootFS FD
117- for (size_t i = 0 ; i < Result;) {
118- linux_dirent_64* Incoming = (linux_dirent_64*)(reinterpret_cast <uint64_t >(dirp) + i);
119- if (FEX::HLE::_SyscallHandler->FM .IsProtectedFile (fd, Incoming->d_ino )) {
120- Result -= Incoming->d_reclen ;
121- memmove (Incoming, (linux_dirent_64*)(reinterpret_cast <uint64_t >(Incoming) + Incoming->d_reclen ), Result - i);
122- continue ;
123- }
124- i += Incoming->d_reclen ;
64+ auto stat (FEXCore::Core::CpuStateFrame* Frame, const char * pathname, FEX::HLE::x64::guest_stat* buf) -> uint64_t {
65+ FaultSafeUserMemAccess::VerifyIsStringReadableMaxSize (pathname, PATH_MAX);
66+ FaultSafeUserMemAccess::VerifyIsWritable (buf, sizeof (*buf));
67+ struct stat host_stat;
68+ uint64_t Result = FEX::HLE::_SyscallHandler->FM .Stat (pathname, &host_stat);
69+ if (Result != -1 ) {
70+ *buf = host_stat;
71+ }
72+ SYSCALL_ERRNO ();
73+ }
74+
75+ auto fstat (FEXCore::Core::CpuStateFrame* Frame, int fd, FEX::HLE::x64::guest_stat* buf) -> uint64_t {
76+ FaultSafeUserMemAccess::VerifyIsWritable (buf, sizeof (*buf));
77+ struct stat host_stat;
78+ uint64_t Result = ::fstat (fd, &host_stat);
79+ if (Result != -1 ) {
80+ *buf = host_stat;
81+ }
82+ SYSCALL_ERRNO ();
83+ }
84+
85+ auto lstat (FEXCore::Core::CpuStateFrame* Frame, const char * path, FEX::HLE::x64::guest_stat* buf) -> uint64_t {
86+ FaultSafeUserMemAccess::VerifyIsStringReadableMaxSize (path, PATH_MAX);
87+ FaultSafeUserMemAccess::VerifyIsWritable (buf, sizeof (*buf));
88+ struct stat host_stat;
89+ uint64_t Result = FEX::HLE::_SyscallHandler->FM .Lstat (path, &host_stat);
90+ if (Result != -1 ) {
91+ *buf = host_stat;
92+ }
93+ SYSCALL_ERRNO ();
94+ }
95+
96+ auto newfstatat (FEXCore::Core::CpuStateFrame* Frame, int dirfd, const char * pathname, FEX::HLE::x64::guest_stat* buf, int flag) -> uint64_t {
97+ FaultSafeUserMemAccess::VerifyIsStringReadableMaxSize (pathname, PATH_MAX);
98+ FaultSafeUserMemAccess::VerifyIsWritable (buf, sizeof (*buf));
99+ struct stat host_stat;
100+ uint64_t Result = FEX::HLE::_SyscallHandler->FM .NewFSStatAt (dirfd, pathname, &host_stat, flag);
101+ if (Result != -1 ) {
102+ *buf = host_stat;
103+ }
104+ SYSCALL_ERRNO ();
105+ }
106+
107+ auto getdents (FEXCore::Core::CpuStateFrame* Frame, int fd, void * dirp, uint32_t count) -> uint64_t {
108+ return GetDentsEmulation<false >(fd, reinterpret_cast <FEX::HLE::x64::linux_dirent*>(dirp), count);
109+ }
110+
111+ auto getdents64 (FEXCore::Core::CpuStateFrame* Frame, int fd, void * dirp, uint32_t count) -> uint64_t {
112+ uint64_t Result = ::syscall (SYSCALL_DEF (getdents64), static_cast <uint64_t >(fd), dirp, static_cast <uint64_t >(count));
113+ if (Result != -1 ) {
114+ // Check for and hide the RootFS FD
115+ for (size_t i = 0 ; i < Result;) {
116+ linux_dirent_64* Incoming = (linux_dirent_64*)(reinterpret_cast <uint64_t >(dirp) + i);
117+ if (FEX::HLE::_SyscallHandler->FM .IsProtectedFile (fd, Incoming->d_ino )) {
118+ Result -= Incoming->d_reclen ;
119+ memmove (Incoming, (linux_dirent_64*)(reinterpret_cast <uint64_t >(Incoming) + Incoming->d_reclen ), Result - i);
120+ continue ;
125121 }
122+ i += Incoming->d_reclen ;
126123 }
127- SYSCALL_ERRNO ();
128- });
129-
130- REGISTER_SYSCALL_IMPL_X64 (dup2, [](FEXCore::Core::CpuStateFrame* Frame, int oldfd, int newfd) -> uint64_t {
131- uint64_t Result = ::dup2 (oldfd, newfd);
132- SYSCALL_ERRNO ();
133- });
134-
135- REGISTER_SYSCALL_IMPL_X64 (statfs, [](FEXCore::Core::CpuStateFrame* Frame, const char * path, struct statfs * buf) -> uint64_t {
136- FaultSafeUserMemAccess::VerifyIsStringReadableMaxSize (path, PATH_MAX);
137- FaultSafeUserMemAccess::VerifyIsWritable (buf, sizeof (*buf));
138- uint64_t Result = FEX::HLE::_SyscallHandler->FM .Statfs (path, buf);
139- SYSCALL_ERRNO ();
140- });
124+ }
125+ SYSCALL_ERRNO ();
126+ }
127+
128+ auto dup2 (FEXCore::Core::CpuStateFrame* Frame, int oldfd, int newfd) -> uint64_t {
129+ uint64_t Result = ::dup2 (oldfd, newfd);
130+ SYSCALL_ERRNO ();
131+ }
132+
133+ auto statfs (FEXCore::Core::CpuStateFrame* Frame, const char * path, struct statfs * buf) -> uint64_t {
134+ FaultSafeUserMemAccess::VerifyIsStringReadableMaxSize (path, PATH_MAX);
135+ FaultSafeUserMemAccess::VerifyIsWritable (buf, sizeof (*buf));
136+ uint64_t Result = FEX::HLE::_SyscallHandler->FM .Statfs (path, buf);
137+ SYSCALL_ERRNO ();
138+ }
139+
140+ void RegisterFD (FEX::HLE::SyscallHandler* Handler) {
141+ REGISTER_SYSCALL_IMPL_X64 (select, select);
142+ REGISTER_SYSCALL_IMPL_X64 (fcntl, fcntl);
143+ REGISTER_SYSCALL_IMPL_X64 (futimesat, futimesat);
144+ REGISTER_SYSCALL_IMPL_X64 (stat, stat);
145+ REGISTER_SYSCALL_IMPL_X64 (fstat, fstat);
146+ REGISTER_SYSCALL_IMPL_X64 (lstat, lstat);
147+ REGISTER_SYSCALL_IMPL_X64 (newfstatat, newfstatat);
148+ REGISTER_SYSCALL_IMPL_X64 (getdents, getdents);
149+ REGISTER_SYSCALL_IMPL_X64 (getdents64, getdents64);
150+ REGISTER_SYSCALL_IMPL_X64 (dup2, dup2);
151+ REGISTER_SYSCALL_IMPL_X64 (statfs, statfs);
141152}
142153} // namespace FEX::HLE::x64
0 commit comments