@@ -393,191 +393,206 @@ uint64_t ForkGuest(FEXCore::Core::InternalThreadState* Thread, FEXCore::Core::Cp
393393 }
394394}
395395
396- void RegisterThread (FEX::HLE::SyscallHandler* Handler) {
397- using namespace FEXCore ::IR;
398-
399- REGISTER_SYSCALL_IMPL (rt_sigreturn, [](FEXCore::Core::CpuStateFrame* Frame) -> uint64_t {
400- FEX::HLE::_SyscallHandler->GetSignalDelegator ()->HandleSignalHandlerReturn (true );
401- FEX_UNREACHABLE;
402- });
403-
404- REGISTER_SYSCALL_IMPL (fork, ([](FEXCore::Core::CpuStateFrame* Frame) -> uint64_t {
405- FEX::HLE::clone3_args args {.Type = TypeOfClone::TYPE_CLONE2,
406- .args = {
407- .flags = 0 ,
408- .pidfd = 0 ,
409- .child_tid = 0 ,
410- .parent_tid = 0 ,
411- .exit_signal = SIGCHLD,
412- .stack = 0 ,
413- .stack_size = 0 ,
414- .tls = 0 ,
415- .set_tid = 0 ,
416- .set_tid_size = 0 ,
417- .cgroup = 0 ,
418- }};
419-
420- return ForkGuest (Frame->Thread , Frame, &args);
421- }));
422-
423- REGISTER_SYSCALL_IMPL (vfork, ([](FEXCore::Core::CpuStateFrame* Frame) -> uint64_t {
424- FEX::HLE::clone3_args args {.Type = TypeOfClone::TYPE_CLONE2,
425- .args = {
426- .flags = CLONE_VFORK,
427- .pidfd = 0 ,
428- .child_tid = 0 ,
429- .parent_tid = 0 ,
430- .exit_signal = SIGCHLD,
431- .stack = 0 ,
432- .stack_size = 0 ,
433- .tls = 0 ,
434- .set_tid = 0 ,
435- .set_tid_size = 0 ,
436- .cgroup = 0 ,
437- }};
438-
439- return ForkGuest (Frame->Thread , Frame, &args);
440- }));
441-
442- REGISTER_SYSCALL_IMPL (getpgrp, [](FEXCore::Core::CpuStateFrame* Frame) -> uint64_t {
443- uint64_t Result = ::getpgrp ();
444- SYSCALL_ERRNO ();
445- });
446-
447- REGISTER_SYSCALL_IMPL (clone3, ([](FEXCore::Core::CpuStateFrame* Frame, FEX::HLE::kernel_clone3_args* cl_args, size_t size) -> uint64_t {
448- FEX::HLE::clone3_args args {};
449- args.Type = TypeOfClone::TYPE_CLONE3;
450- memcpy (&args.args , cl_args, std::min (sizeof (FEX::HLE::kernel_clone3_args), size));
451- return CloneHandler (Frame, &args);
452- }));
453-
454- REGISTER_SYSCALL_IMPL (exit, [](FEXCore::Core::CpuStateFrame* Frame, int status) -> uint64_t {
455- // TLS/DTV teardown is something FEX can't control. Disable glibc checking when we leave a pthread.
456- // Since this thread is hard stopping, we can't track the TLS/DTV teardown in FEX's thread handling.
457- FEXCore::Allocator::YesIKnowImNotSupposedToUseTheGlibcAllocator::HardDisable ();
458- auto ThreadObject = FEX::HLE::ThreadManager::GetStateObjectFromCPUState (Frame);
459-
460- if (ThreadObject->ThreadInfo .clear_child_tid ) {
461- auto Addr = std::atomic_ref<int32_t >(*ThreadObject->ThreadInfo .clear_child_tid );
462- Addr.store (0 );
463- syscall (SYSCALL_DEF (futex), ThreadObject->ThreadInfo .clear_child_tid , FUTEX_WAKE, ~0ULL , 0 , 0 , 0 );
464- }
396+ using namespace FEXCore ::IR;
465397
466- ThreadObject->StatusCode = status;
398+ auto rt_sigreturn (FEXCore::Core::CpuStateFrame* Frame) -> uint64_t {
399+ FEX::HLE::_SyscallHandler->GetSignalDelegator ()->HandleSignalHandlerReturn (true );
400+ FEX_UNREACHABLE;
401+ }
467402
468- FEX::HLE::_SyscallHandler->UninstallTLSState (ThreadObject);
403+ auto fork (FEXCore::Core::CpuStateFrame* Frame) -> uint64_t {
404+ FEX::HLE::clone3_args args {.Type = TypeOfClone::TYPE_CLONE2,
405+ .args = {
406+ .flags = 0 ,
407+ .pidfd = 0 ,
408+ .child_tid = 0 ,
409+ .parent_tid = 0 ,
410+ .exit_signal = SIGCHLD,
411+ .stack = 0 ,
412+ .stack_size = 0 ,
413+ .tls = 0 ,
414+ .set_tid = 0 ,
415+ .set_tid_size = 0 ,
416+ .cgroup = 0 ,
417+ }};
418+
419+ return ForkGuest (Frame->Thread , Frame, &args);
420+ }
469421
470- if (ThreadObject->ExecutionThread ) {
471- // If this is a pthread based execution thread, then there is more work to be done.
472- // Delegate final deletion and cleanup to the pthreads Thread management.
473- FEX::LinuxEmulation::Threads::LongjumpDeallocateAndExit (ThreadObject, status);
474- } else {
475- FEX::HLE::_SyscallHandler->TM .DestroyThread (ThreadObject, true );
476- FEX::LinuxEmulation::Threads::DeallocateStackObjectAndExit (nullptr , status);
477- }
478- // This will never be reached
479- std::terminate ();
480- });
481-
482- REGISTER_SYSCALL_IMPL (prctl,
483- [](FEXCore::Core::CpuStateFrame* Frame, int option, unsigned long arg2, unsigned long arg3, unsigned long arg4,
484- unsigned long arg5) -> uint64_t {
485- uint64_t Result {};
422+ auto vfork (FEXCore::Core::CpuStateFrame* Frame) -> uint64_t {
423+ FEX::HLE::clone3_args args {.Type = TypeOfClone::TYPE_CLONE2,
424+ .args = {
425+ .flags = CLONE_VFORK,
426+ .pidfd = 0 ,
427+ .child_tid = 0 ,
428+ .parent_tid = 0 ,
429+ .exit_signal = SIGCHLD,
430+ .stack = 0 ,
431+ .stack_size = 0 ,
432+ .tls = 0 ,
433+ .set_tid = 0 ,
434+ .set_tid_size = 0 ,
435+ .cgroup = 0 ,
436+ }};
437+
438+ return ForkGuest (Frame->Thread , Frame, &args);
439+ }
440+
441+ auto getpgrp (FEXCore::Core::CpuStateFrame* Frame) -> uint64_t {
442+ uint64_t Result = ::getpgrp ();
443+ SYSCALL_ERRNO ();
444+ }
445+
446+ auto clone3 (FEXCore::Core::CpuStateFrame* Frame, FEX::HLE::kernel_clone3_args* cl_args, size_t size) -> uint64_t {
447+ FEX::HLE::clone3_args args {};
448+ args.Type = TypeOfClone::TYPE_CLONE3;
449+ memcpy (&args.args , cl_args, std::min (sizeof (FEX::HLE::kernel_clone3_args), size));
450+ return CloneHandler (Frame, &args);
451+ }
452+
453+ auto exit (FEXCore::Core::CpuStateFrame* Frame, int status) -> uint64_t {
454+ // TLS/DTV teardown is something FEX can't control. Disable glibc checking when we leave a pthread.
455+ // Since this thread is hard stopping, we can't track the TLS/DTV teardown in FEX's thread handling.
456+ FEXCore::Allocator::YesIKnowImNotSupposedToUseTheGlibcAllocator::HardDisable ();
457+ auto ThreadObject = FEX::HLE::ThreadManager::GetStateObjectFromCPUState (Frame);
458+
459+ if (ThreadObject->ThreadInfo .clear_child_tid ) {
460+ auto Addr = std::atomic_ref<int32_t >(*ThreadObject->ThreadInfo .clear_child_tid );
461+ Addr.store (0 );
462+ syscall (SYSCALL_DEF (futex), ThreadObject->ThreadInfo .clear_child_tid , FUTEX_WAKE, ~0ULL , 0 , 0 , 0 );
463+ }
464+
465+ ThreadObject->StatusCode = status;
466+
467+ FEX::HLE::_SyscallHandler->UninstallTLSState (ThreadObject);
468+
469+ if (ThreadObject->ExecutionThread ) {
470+ // If this is a pthread based execution thread, then there is more work to be done.
471+ // Delegate final deletion and cleanup to the pthreads Thread management.
472+ FEX::LinuxEmulation::Threads::LongjumpDeallocateAndExit (ThreadObject, status);
473+ } else {
474+ FEX::HLE::_SyscallHandler->TM .DestroyThread (ThreadObject, true );
475+ FEX::LinuxEmulation::Threads::DeallocateStackObjectAndExit (nullptr , status);
476+ }
477+ // This will never be reached
478+ std::terminate ();
479+ }
480+
481+ auto prctl (FEXCore::Core::CpuStateFrame* Frame, int option, unsigned long arg2, unsigned long arg3, unsigned long arg4, unsigned long arg5)
482+ -> uint64_t {
483+ uint64_t Result {};
486484#ifndef PR_GET_AUXV
487485#define PR_GET_AUXV 0x41555856
488486#endif
489- switch (option) {
490- case PR_SET_SECCOMP: {
491- uint32_t Operation {};
492- if (arg2 == SECCOMP_MODE_STRICT) Operation = SECCOMP_SET_MODE_STRICT;
493- if (arg2 == SECCOMP_MODE_FILTER) Operation = SECCOMP_SET_MODE_FILTER;
494-
495- return FEX::HLE::_SyscallHandler->SeccompEmulator .Handle (Frame, Operation, 0 , reinterpret_cast <void *>(arg3));
496- }
497- case PR_GET_SECCOMP: return FEX::HLE::_SyscallHandler->SeccompEmulator .GetSeccomp (Frame);
498- case PR_GET_AUXV: {
499- if (arg4 || arg5) {
500- return -EINVAL;
501- }
502-
503- void * addr = reinterpret_cast <void *>(arg2);
504- size_t UserSize = reinterpret_cast <size_t >(arg3);
505-
506- const auto auxv = FEX::HLE::_SyscallHandler->GetCodeLoader ()->GetAuxv ();
507- const auto auxvBase = auxv.address ;
508- const auto auxvSize = auxv.size ;
509- size_t MinSize = std::min (auxvSize, UserSize);
510-
511- memcpy (addr, reinterpret_cast <void *>(auxvBase), MinSize);
512-
513- // Returns the size of auxv without truncation.
514- return auxvSize;
515- }
516- default : Result = ::prctl (option, arg2, arg3, arg4, arg5); break ;
517- }
518- SYSCALL_ERRNO ();
519- });
520-
521- REGISTER_SYSCALL_IMPL (arch_prctl, [](FEXCore::Core::CpuStateFrame* Frame, int code, unsigned long addr) -> uint64_t {
522- uint64_t Result {};
523- switch (code) {
524- case 0x1001 : // ARCH_SET_GS
525- if (addr >= SyscallHandler::TASK_MAX_64BIT) {
526- // Ignore a non-canonical address
527- return -EPERM;
528- }
529- Frame->State .gs_cached = addr;
530- Result = 0 ;
531- break ;
532- case 0x1002 : // ARCH_SET_FS
533- if (addr >= SyscallHandler::TASK_MAX_64BIT) {
534- // Ignore a non-canonical address
535- return -EPERM;
536- }
537- Frame->State .fs_cached = addr;
538- Result = 0 ;
539- break ;
540- case 0x1003 : // ARCH_GET_FS
541- *reinterpret_cast <uint64_t *>(addr) = Frame->State .fs_cached ;
542- Result = 0 ;
543- break ;
544- case 0x1004 : // ARCH_GET_GS
545- *reinterpret_cast <uint64_t *>(addr) = Frame->State .gs_cached ;
546- Result = 0 ;
547- break ;
548- case 0x3001 : // ARCH_CET_STATUS
549- Result = -EINVAL; // We don't support CET, return EINVAL
550- break ;
551- case 0x1011 : // ARCH_GET_CPUID
552- return 1 ;
553- break ;
554- case 0x1012 : // ARCH_SET_CPUID
555- return -ENODEV; // Claim we don't support faulting on CPUID
556- break ;
557- default :
558- LogMan::Msg::EFmt (" Unknown prctl: 0x{:x}" , code);
559- Result = -EINVAL;
560- break ;
487+ switch (option) {
488+ case PR_SET_SECCOMP: {
489+ uint32_t Operation {};
490+ if (arg2 == SECCOMP_MODE_STRICT) {
491+ Operation = SECCOMP_SET_MODE_STRICT;
492+ }
493+ if (arg2 == SECCOMP_MODE_FILTER) {
494+ Operation = SECCOMP_SET_MODE_FILTER;
495+ }
496+
497+ return FEX::HLE::_SyscallHandler->SeccompEmulator .Handle (Frame, Operation, 0 , reinterpret_cast <void *>(arg3));
498+ }
499+ case PR_GET_SECCOMP: return FEX::HLE::_SyscallHandler->SeccompEmulator .GetSeccomp (Frame);
500+ case PR_GET_AUXV: {
501+ if (arg4 || arg5) {
502+ return -EINVAL;
561503 }
562- SYSCALL_ERRNO ();
563- });
564504
565- REGISTER_SYSCALL_IMPL (set_tid_address, [](FEXCore::Core::CpuStateFrame* Frame, int * tidptr) -> uint64_t {
566- auto ThreadObject = FEX::HLE::ThreadManager::GetStateObjectFromCPUState (Frame);
567- ThreadObject->ThreadInfo .clear_child_tid = tidptr;
568- return ThreadObject->ThreadInfo .TID ;
569- });
505+ void * addr = reinterpret_cast <void *>(arg2);
506+ size_t UserSize = reinterpret_cast <size_t >(arg3);
570507
571- REGISTER_SYSCALL_IMPL (exit_group, [](FEXCore::Core::CpuStateFrame* Frame, int status) -> uint64_t {
572- Frame->Thread ->CTX ->FlushAndCloseCodeMap ();
508+ const auto auxv = FEX::HLE::_SyscallHandler->GetCodeLoader ()->GetAuxv ();
509+ const auto auxvBase = auxv.address ;
510+ const auto auxvSize = auxv.size ;
511+ size_t MinSize = std::min (auxvSize, UserSize);
573512
574- // Save telemetry if we're exiting.
575- FEX::HLE::_SyscallHandler->GetSignalDelegator ()->SaveTelemetry ();
576- FEX::HLE::_SyscallHandler->TM .CleanupForExit ();
513+ memcpy (addr, reinterpret_cast <void *>(auxvBase), MinSize);
577514
578- syscall (SYSCALL_DEF (exit_group), status);
579- // This will never be reached
580- std::terminate ();
581- });
515+ // Returns the size of auxv without truncation.
516+ return auxvSize;
517+ }
518+ default : Result = ::prctl (option, arg2, arg3, arg4, arg5); break ;
519+ }
520+ SYSCALL_ERRNO ();
521+ }
522+
523+ auto arch_prctl (FEXCore::Core::CpuStateFrame* Frame, int code, unsigned long addr) -> uint64_t {
524+ uint64_t Result {};
525+ switch (code) {
526+ case 0x1001 : // ARCH_SET_GS
527+ if (addr >= SyscallHandler::TASK_MAX_64BIT) {
528+ // Ignore a non-canonical address
529+ return -EPERM;
530+ }
531+ Frame->State .gs_cached = addr;
532+ Result = 0 ;
533+ break ;
534+ case 0x1002 : // ARCH_SET_FS
535+ if (addr >= SyscallHandler::TASK_MAX_64BIT) {
536+ // Ignore a non-canonical address
537+ return -EPERM;
538+ }
539+ Frame->State .fs_cached = addr;
540+ Result = 0 ;
541+ break ;
542+ case 0x1003 : // ARCH_GET_FS
543+ *reinterpret_cast <uint64_t *>(addr) = Frame->State .fs_cached ;
544+ Result = 0 ;
545+ break ;
546+ case 0x1004 : // ARCH_GET_GS
547+ *reinterpret_cast <uint64_t *>(addr) = Frame->State .gs_cached ;
548+ Result = 0 ;
549+ break ;
550+ case 0x3001 : // ARCH_CET_STATUS
551+ Result = -EINVAL; // We don't support CET, return EINVAL
552+ break ;
553+ case 0x1011 : // ARCH_GET_CPUID
554+ return 1 ;
555+ break ;
556+ case 0x1012 : // ARCH_SET_CPUID
557+ return -ENODEV; // Claim we don't support faulting on CPUID
558+ break ;
559+ default :
560+ LogMan::Msg::EFmt (" Unknown prctl: 0x{:x}" , code);
561+ Result = -EINVAL;
562+ break ;
563+ }
564+ SYSCALL_ERRNO ();
565+ }
566+
567+ auto set_tid_address (FEXCore::Core::CpuStateFrame* Frame, int * tidptr) -> uint64_t {
568+ auto ThreadObject = FEX::HLE::ThreadManager::GetStateObjectFromCPUState (Frame);
569+ ThreadObject->ThreadInfo .clear_child_tid = tidptr;
570+ return ThreadObject->ThreadInfo .TID ;
571+ }
572+
573+ auto exit_group (FEXCore::Core::CpuStateFrame* Frame, int status) -> uint64_t {
574+ Frame->Thread ->CTX ->FlushAndCloseCodeMap ();
575+
576+ // Save telemetry if we're exiting.
577+ FEX::HLE::_SyscallHandler->GetSignalDelegator ()->SaveTelemetry ();
578+ FEX::HLE::_SyscallHandler->TM .CleanupForExit ();
579+
580+ syscall (SYSCALL_DEF (exit_group), status);
581+ // This will never be reached
582+ std::terminate ();
583+ }
584+
585+
586+ void RegisterThread (FEX::HLE::SyscallHandler* Handler) {
587+ REGISTER_SYSCALL_IMPL (rt_sigreturn, rt_sigreturn);
588+ REGISTER_SYSCALL_IMPL (fork, fork);
589+ REGISTER_SYSCALL_IMPL (vfork, vfork);
590+ REGISTER_SYSCALL_IMPL (getpgrp, getpgrp);
591+ REGISTER_SYSCALL_IMPL (clone3, clone3);
592+ REGISTER_SYSCALL_IMPL (exit, exit);
593+ REGISTER_SYSCALL_IMPL (prctl, prctl);
594+ REGISTER_SYSCALL_IMPL (arch_prctl, arch_prctl);
595+ REGISTER_SYSCALL_IMPL (set_tid_address, set_tid_address);
596+ REGISTER_SYSCALL_IMPL (exit_group, exit_group);
582597}
583598} // namespace FEX::HLE
0 commit comments