@@ -73,6 +73,54 @@ static Cvar::Cvar<bool> workaround_naclSystem_freebsd_disableQualification(
7373 " Disable platform qualification when running Linux NaCl loader on FreeBSD through Linuxulator" ,
7474 Cvar::NONE, true );
7575
76+ #if defined(DAEMON_NACL_BOX64_EMULATION)
77+ static Cvar::Cvar<bool > workaround_box64_disableQualification (
78+ " workaround.ppc64el.box64.disableQualification" ,
79+ " Disable platform qualification when running amd64 NaCl loader under Box64 emulation" ,
80+ Cvar::NONE, true );
81+
82+ static Cvar::Cvar<bool > workaround_box64_disableBootstrap (
83+ " workaround.ppc64el.box64.disableBootstrap" ,
84+ " Disable NaCl bootstrap helper when using Box64 emulation" ,
85+ Cvar::NONE, true );
86+
87+ static Cvar::Cvar<std::string> vm_box64_path (
88+ " vm.box64.path" ,
89+ " Path to the box64 binary for NaCl emulation (empty = search PATH)" ,
90+ Cvar::NONE, " " );
91+
92+ // Resolve box64 binary path by searching PATH if not explicitly set.
93+ static std::string ResolveBox64Path () {
94+ std::string path = vm_box64_path.Get ();
95+ if (!path.empty ()) {
96+ return path;
97+ }
98+
99+ const char * envPath = getenv (" PATH" );
100+ if (!envPath) {
101+ Sys::Error (" Box64 emulation is enabled but PATH is not set and vm.box64.path is empty." );
102+ }
103+
104+ std::string pathStr (envPath);
105+ size_t start = 0 ;
106+ while (start < pathStr.size ()) {
107+ size_t end = pathStr.find (' :' , start);
108+ if (end == std::string::npos) {
109+ end = pathStr.size ();
110+ }
111+ std::string candidate = pathStr.substr (start, end - start) + " /box64" ;
112+ if (access (candidate.c_str (), X_OK) == 0 ) {
113+ return candidate;
114+ }
115+ start = end + 1 ;
116+ }
117+
118+ Sys::Error (" Box64 emulation is enabled but 'box64' was not found in PATH. "
119+ " Install Box64 or set vm.box64.path to the full path of the box64 binary." );
120+ return " " ; // unreachable
121+ }
122+ #endif
123+
76124static Cvar::Cvar<bool > vm_nacl_qualification (
77125 " vm.nacl.qualification" ,
78126 " Enable NaCl loader platform qualification" ,
@@ -255,6 +303,9 @@ static std::pair<Sys::OSHandle, IPC::Socket> CreateNaClVM(std::pair<IPC::Socket,
255303 char rootSocketRedir[32 ];
256304 std::string module , nacl_loader, irt, bootstrap, modulePath, verbosity;
257305 FS::File stderrRedirect;
306+ #if defined(DAEMON_NACL_BOX64_EMULATION)
307+ std::string box64Path;
308+ #endif
258309#if !defined(_WIN32) || defined(_WIN64)
259310 constexpr bool win32Force64Bit = false ;
260311#else
@@ -304,6 +355,33 @@ static std::pair<Sys::OSHandle, IPC::Socket> CreateNaClVM(std::pair<IPC::Socket,
304355 }
305356
306357#if defined(__linux__) || defined(__FreeBSD__)
358+ #if defined(DAEMON_NACL_BOX64_EMULATION)
359+ /* Use Box64 to run the x86_64 NaCl loader on non-x86 architectures.
360+ The bootstrap helper uses a double-exec pattern that Box64 cannot handle,
361+ so we skip it and prepend "box64" to the nacl_loader command instead. */
362+ if (!workaround_box64_disableBootstrap.Get () && vm_nacl_bootstrap.Get ()) {
363+ bootstrap = FS::Path::Build (naclPath, " nacl_helper_bootstrap" );
364+
365+ if (!FS::RawPath::FileExists (bootstrap)) {
366+ Sys::Error (" NaCl bootstrap helper not found: %s" , bootstrap);
367+ }
368+
369+ args.push_back (bootstrap.c_str ());
370+ args.push_back (nacl_loader.c_str ());
371+ args.push_back (" --r_debug=0xXXXXXXXXXXXXXXXX" );
372+ args.push_back (" --reserved_at_zero=0xXXXXXXXXXXXXXXXX" );
373+ } else {
374+ if (workaround_box64_disableBootstrap.Get ()) {
375+ Log::Notice (" Skipping NaCl bootstrap helper for Box64 emulation." );
376+ } else {
377+ Log::Warn (" Not using NaCl bootstrap helper." );
378+ }
379+ box64Path = ResolveBox64Path ();
380+ Log::Notice (" Using Box64 emulator: %s" , box64Path);
381+ args.push_back (box64Path.c_str ());
382+ args.push_back (nacl_loader.c_str ());
383+ }
384+ #else
307385 if (vm_nacl_bootstrap.Get ()) {
308386#if defined(DAEMON_ARCH_arm64)
309387 bootstrap = FS::Path::Build (naclPath, " nacl_helper_bootstrap-armhf" );
@@ -323,6 +401,7 @@ static std::pair<Sys::OSHandle, IPC::Socket> CreateNaClVM(std::pair<IPC::Socket,
323401 Log::Warn (" Not using NaCl bootstrap helper." );
324402 args.push_back (nacl_loader.c_str ());
325403 }
404+ #endif
326405#else
327406 Q_UNUSED (bootstrap);
328407 args.push_back (nacl_loader.c_str ());
@@ -381,6 +460,17 @@ static std::pair<Sys::OSHandle, IPC::Socket> CreateNaClVM(std::pair<IPC::Socket,
381460 enableQualification = false ;
382461 }
383462#endif
463+
464+ #if defined(DAEMON_NACL_BOX64_EMULATION)
465+ /* When running the amd64 NaCl loader under Box64, the loader's
466+ platform qualification will fail because the CPU is not actually x86_64.
467+ Disabling qualification allows the emulated loader to proceed. */
468+
469+ if (workaround_box64_disableQualification.Get ()) {
470+ Log::Warn (" Disabling NaCL platform qualification for Box64 emulation." );
471+ enableQualification = false ;
472+ }
473+ #endif
384474 }
385475 else {
386476 Log::Warn (" Not using NaCl platform qualification." );
0 commit comments