@@ -354,6 +354,89 @@ static std::pair<Sys::OSHandle, IPC::Socket> InternalLoadModule(std::pair<IPC::S
354354}
355355
356356#if defined(DAEMON_NACL_RUNTIME_ENABLED)
357+
358+ #if defined(__linux__) || defined(DAEMON_LINUXULATOR)
359+ #if defined(YOKAI_ARCH_ARM64)
360+ enum class ArmhfSupport
361+ {
362+ Supported,
363+ Unsupported,
364+ Unknown,
365+ };
366+
367+ static void SilenceOutput ()
368+ {
369+ int devnull = open (" /dev/null" , O_WRONLY );
370+
371+ if (devnull < 0 ) {
372+ _exit (200 );
373+ }
374+
375+ dup2 (devnull, STDOUT_FILENO );
376+ dup2 (devnull, STDERR_FILENO );
377+
378+ close (devnull);
379+ }
380+
381+ static ArmhfSupport CheckArmhfSupport (Str::StringRef probe)
382+ {
383+ pid_t pid = fork ();
384+ if (pid < 0 ) {
385+ return ArmhfSupport::Unknown;
386+ }
387+
388+ if (pid == 0 ) {
389+ SilenceOutput ();
390+
391+ char *const argv[] = {
392+ const_cast <char *>(probe.data ()),
393+ nullptr ,
394+ };
395+
396+ execve (probe.data (), argv, environ);
397+
398+ switch (errno)
399+ {
400+ case ENOEXEC :
401+ // Kernel cannot execute the probe.
402+ _exit (100 );
403+
404+ case ENOENT :
405+ case EACCES :
406+ // Missing or inaccessible probe.
407+ _exit (101 );
408+
409+ default :
410+ _exit (102 );
411+ }
412+ }
413+
414+ int status;
415+ if (waitpid (pid, &status, 0 ) < 0 ) {
416+ return ArmhfSupport::Unknown;
417+ }
418+
419+ if (!WIFEXITED (status)) {
420+ return ArmhfSupport::Unknown;
421+ }
422+
423+ switch (WEXITSTATUS (status))
424+ {
425+ case 100 :
426+ return ArmhfSupport::Unsupported;
427+
428+ case 101 :
429+ case 102 :
430+ return ArmhfSupport::Unknown;
431+
432+ default :
433+ // The execve() call succeeded, so the probe has been executed properly.
434+ return ArmhfSupport::Supported;
435+ }
436+ }
437+ #endif // NACL_ARCH_ARM64
438+ #endif // defined(__linux__) || defined(DAEMON_LINUXULATOR)
439+
357440static std::pair<Sys::OSHandle, IPC ::Socket> CreateNaClVM (std::pair<IPC ::Socket, IPC ::Socket> pair, Str::StringRef name, bool debug, bool extract, int debugLoader) {
358441 CheckMinAddressSysctlTooLarge ();
359442 const std::string& libPath = FS::GetLibPath ();
@@ -423,8 +506,27 @@ static std::pair<Sys::OSHandle, IPC::Socket> CreateNaClVM(std::pair<IPC::Socket,
423506 // Only use armhf on arm64 when the hardware can do 32-bit.
424507 bool useLdArmhf = hasLdArmhf && hasArmhf;
425508
509+ #if defined(__linux__) || defined(DAEMON_LINUXULATOR)
426510#if defined(YOKAI_ARCH_ARM64)
427- // TODO: Detect that the arm64 processor supports 32-bit hardware support.
511+ std::string ldLoaderPath = FS::Path::Build (libPath, " libs-linux-armhf" );
512+ ldLoaderPath = FS::Path::Build (ldLoaderPath, " ld-linux-armhf.so.3" );
513+
514+ switch (CheckArmhfSupport (ldLoaderPath))
515+ {
516+ case ArmhfSupport::Supported:
517+ Log::Notice (" Working armhf multiarch support." );
518+ break ;
519+
520+ case ArmhfSupport::Unsupported:
521+ Log::Notice (" Unsupported armhf multiarch." );
522+ useLdArmhf = false ;
523+ break ;
524+
525+ case ArmhfSupport::Unknown:
526+ Log::Warn (" Could not determine armhf multiarch support." );
527+ useLdArmhf = false ;
528+ break ;
529+ }
428530
429531 if (useLdArmhf) {
430532 if (!workaround_box64_preferArmhf.Get ()) {
@@ -434,7 +536,8 @@ static std::pair<Sys::OSHandle, IPC::Socket> CreateNaClVM(std::pair<IPC::Socket,
434536 Log::Notice (" Preferring armhf multiarch over Box64 emulation." );
435537 }
436538 }
437- #endif
539+ #endif // defined(YOKAI_ARCH_ARM64)
540+ #endif // defined(__linux__) || defined(DAEMON_LINUXULATOR)
438541
439542 // Only use rbox64 on arm64 when the hardware cannot do 32-bit.
440543 bool useBox64 = hasBox64 && !useLdArmhf;
0 commit comments