Skip to content

Commit 40ff96d

Browse files
committed
virtualmachine: detect armhf multiarch support
1 parent dfb4c51 commit 40ff96d

1 file changed

Lines changed: 105 additions & 2 deletions

File tree

‎src/engine/framework/VirtualMachine.cpp‎

Lines changed: 105 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -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+
357440
static 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

Comments
 (0)