diff --git a/CMakeLists.txt b/CMakeLists.txt index 0fb9eeb87..970e702a9 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -46,6 +46,25 @@ else() set(CMAKE_INTERPROCEDURAL_OPTIMIZATION FALSE) endif() +if (CMAKE_SYSTEM_PROCESSOR MATCHES "x86_64") + option(ENABLE_X86_HOST_DEBUG "Enables compiling on x86_64 host" FALSE) + if (NOT ENABLE_X86_HOST_DEBUG) + message(FATAL_ERROR + " Be warned: FEX isn't optimized for x86_64 hosts!\n" + " Support for x86_64 hosts is only for debugging and convenience!\n" + " Don't expect amazing performance or optimal code generation!\n" + " Pass -DENABLE_X86_HOST_DEBUG=True to bypass this message!") + endif() + set(_M_X86_64 1) + add_definitions(-D_M_X86_64=1) + set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -mcx16") +endif() + +if (CMAKE_SYSTEM_PROCESSOR MATCHES "aarch64") + set(_M_ARM_64 1) + add_definitions(-D_M_ARM_64=1) +endif() + find_program(CCACHE_PROGRAM ccache) if(CCACHE_PROGRAM) message(STATUS "CCache enabled") @@ -64,8 +83,8 @@ if (ENABLE_LLD) endif() if (ENABLE_STATIC_PIE) - if (NOT ENABLE_LLD) - message (FATAL_ERROR "static-pie requires linking with lld") + if (_M_ARM_64 AND ENABLE_LLD) + message (FATAL_ERROR "Static linking does not currently work with AArch64+LLD. Use GNU ld for now.") endif() file(WRITE ${PROJECT_BINARY_DIR}/CMakeFiles/CMakeTmp/Determine_iplt.c @@ -129,7 +148,56 @@ if (ENABLE_STATIC_PIE) set (STATIC_PIE_OPTIONS "-static-pie") # Pthreads has an issue with exposing symbols # We need to make some concessions to the pthread gods - set (PTHREAD_LIB -Wl,--undefined-glob=pthread_* pthread) + if (ENABLE_LLD) + set (PTHREAD_LIB + -Wl,--undefined-glob=pthread_* + -Wl,--undefined=__cxa_finalize + -Wl,--undefined=_pthread_cleanup_push_defer + -Wl,--undefined=_pthread_cleanup_pop_restore + -Wl,--undefined=__pthread_cleanup_upto + pthread) + else() + set (PTHREAD_LIB + -Wl,--undefined=pthread_join + -Wl,--undefined=pthread_attr_getdetachstate + -Wl,--undefined=pthread_sigmask + -Wl,--undefined=pthread_mutex_lock + -Wl,--undefined=pthread_cond_init + -Wl,--undefined=pthread_attr_init + -Wl,--undefined=pthread_mutex_unlock + -Wl,--undefined=pthread_mutexattr_destroy + -Wl,--undefined=pthread_detach + -Wl,--undefined=pthread_mutex_init + -Wl,--undefined=pthread_getattr_np + -Wl,--undefined=pthread_cond_timedwait + -Wl,--undefined=pthread_attr_destroy + -Wl,--undefined=pthread_mutexattr_settype + -Wl,--undefined=pthread_rwlock_unlock + -Wl,--undefined=pthread_rwlock_wrlock + -Wl,--undefined=pthread_setspecific + -Wl,--undefined=pthread_create + -Wl,--undefined=pthread_cond_clockwait + -Wl,--undefined=pthread_key_create + -Wl,--undefined=pthread_rwlock_rdlock + -Wl,--undefined=pthread_setname_np + -Wl,--undefined=pthread_cond_signal + -Wl,--undefined=pthread_mutexattr_init + -Wl,--undefined=pthread_attr_setstack + -Wl,--undefined=pthread_self + -Wl,--undefined=pthread_getaffinity_np + -Wl,--undefined=pthread_cond_wait + -Wl,--undefined=pthread_mutex_trylock + -Wl,--undefined=pthread_cond_broadcast + -Wl,--undefined=pthread_cond_destroy + -Wl,--undefined=pthread_getspecific + -Wl,--undefined=pthread_key_delete + -Wl,--undefined=pthread_once + -Wl,--undefined=__cxa_finalize + -Wl,--undefined=_pthread_cleanup_push_defer + -Wl,--undefined=_pthread_cleanup_pop_restore + -Wl,--undefined=__pthread_cleanup_upto + pthread) + endif() else() message (FATAL_ERROR "Application has __rela_iplt_{start,end} symbols. Which means static-pie can't be enabled") endif() @@ -165,25 +233,6 @@ set (CMAKE_LINKER_FLAGS_RELWITHDEBINFO "${CMAKE_LINKER_FLAGS_RELWITHDEBINFO} -fn set (CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -fomit-frame-pointer") set (CMAKE_LINKER_FLAGS_RELEASE "${CMAKE_LINKER_FLAGS_RELEASE} -fomit-frame-pointer") -if (CMAKE_SYSTEM_PROCESSOR MATCHES "x86_64") - option(ENABLE_X86_HOST_DEBUG "Enables compiling on x86_64 host" FALSE) - if (NOT ENABLE_X86_HOST_DEBUG) - message(FATAL_ERROR - " Be warned: FEX isn't optimized for x86_64 hosts!\n" - " Support for x86_64 hosts is only for debugging and convenience!\n" - " Don't expect amazing performance or optimal code generation!\n" - " Pass -DENABLE_X86_HOST_DEBUG=True to bypass this message!") - endif() - set(_M_X86_64 1) - add_definitions(-D_M_X86_64=1) - set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -mcx16") -endif() - -if (CMAKE_SYSTEM_PROCESSOR MATCHES "aarch64") - set(_M_ARM_64 1) - add_definitions(-D_M_ARM_64=1) -endif() - add_subdirectory(External/vixl/) include_directories(External/vixl/src/) diff --git a/External/FEXCore/Source/Common/Paths.cpp b/External/FEXCore/Source/Common/Paths.cpp index 54e5f0440..9e5125110 100644 --- a/External/FEXCore/Source/Common/Paths.cpp +++ b/External/FEXCore/Source/Common/Paths.cpp @@ -36,9 +36,10 @@ namespace FEXCore::Paths { *CachePath += "/.fex-emu/"; *EntryCache = *CachePath + "/EntryCache/"; + std::error_code ec{}; // Ensure the folder structure is created for our Data - if (!std::filesystem::exists(*EntryCache) && - !std::filesystem::create_directories(*EntryCache)) { + if (!std::filesystem::exists(*EntryCache, ec) && + !std::filesystem::create_directories(*EntryCache, ec)) { LogMan::Msg::D("Couldn't create EntryCache directory: '%s'", EntryCache->c_str()); } } diff --git a/External/FEXCore/Source/Interface/Config/Config.cpp b/External/FEXCore/Source/Interface/Config/Config.cpp index 989938b37..e02ff8776 100644 --- a/External/FEXCore/Source/Interface/Config/Config.cpp +++ b/External/FEXCore/Source/Interface/Config/Config.cpp @@ -59,9 +59,9 @@ namespace FEXCore::Config { } // Ensure the folder structure is created for our configuration - if (!std::filesystem::exists(ConfigDir) && - !std::filesystem::create_directories(ConfigDir)) { - LogMan::Msg::D("Couldn't create config directory: '%s'", ConfigDir.c_str()); + std::error_code ec{}; + if (!std::filesystem::exists(ConfigDir, ec) && + !std::filesystem::create_directories(ConfigDir, ec)) { // Let's go local in this case return "./"; } @@ -85,9 +85,11 @@ namespace FEXCore::Config { std::string GetApplicationConfig(const std::string &Filename, bool Global) { std::string ConfigFile = GetConfigDirectory(Global); + + std::error_code ec{}; if (!Global && - !std::filesystem::exists(ConfigFile) && - !std::filesystem::create_directories(ConfigFile)) { + !std::filesystem::exists(ConfigFile, ec) && + !std::filesystem::create_directories(ConfigFile, ec)) { LogMan::Msg::D("Couldn't create config directory: '%s'", ConfigFile.c_str()); // Let's go local in this case return "./" + Filename + ".json"; @@ -97,9 +99,8 @@ namespace FEXCore::Config { // Attempt to create the local folder if it doesn't exist if (!Global && - !std::filesystem::exists(ConfigFile) && - !std::filesystem::create_directories(ConfigFile)) { - LogMan::Msg::D("Couldn't create AppConfig directory: '%s'", ConfigFile.c_str()); + !std::filesystem::exists(ConfigFile, ec) && + !std::filesystem::create_directories(ConfigFile, ec)) { // Let's go local in this case return "./" + Filename + ".json"; } @@ -273,7 +274,8 @@ namespace FEXCore::Config { Path = std::filesystem::absolute(Path); // Only return if it exists - if (std::filesystem::exists(Path)) { + std::error_code ec{}; + if (std::filesystem::exists(Path, ec)) { return Path; } } @@ -309,7 +311,8 @@ namespace FEXCore::Config { else if (!PathName().empty()) { // If the filesystem doesn't exist then let's see if it exists in the fex-emu folder std::string NamedRootFS = GetDataDirectory() + "RootFS/" + PathName(); - if (std::filesystem::exists(NamedRootFS)) { + std::error_code ec{}; + if (std::filesystem::exists(NamedRootFS, ec)) { FEXCore::Config::EraseSet(FEXCore::Config::CONFIG_ROOTFS, NamedRootFS); } } @@ -332,7 +335,8 @@ namespace FEXCore::Config { else if (!PathName().empty()) { // If the filesystem doesn't exist then let's see if it exists in the fex-emu folder std::string NamedConfig = GetDataDirectory() + "ThunkConfigs/" + PathName(); - if (std::filesystem::exists(NamedConfig)) { + std::error_code ec{}; + if (std::filesystem::exists(NamedConfig, ec)) { FEXCore::Config::EraseSet(FEXCore::Config::CONFIG_THUNKCONFIG, NamedConfig); } } diff --git a/Source/Common/RootFSSetup.cpp b/Source/Common/RootFSSetup.cpp index 9b4e6ce9d..0049b0aa8 100644 --- a/Source/Common/RootFSSetup.cpp +++ b/Source/Common/RootFSSetup.cpp @@ -21,7 +21,8 @@ static std::fstream SquashFSLock{}; bool SanityCheckPath(std::string const &LDPath) { // Check if we have an directory inside our temp folder std::string PathUser = LDPath + "/usr"; - if (!std::filesystem::exists(PathUser)) { + std::error_code ec{}; + if (!std::filesystem::exists(PathUser, ec)) { LogMan::Msg::D("Child couldn't mount rootfs, /usr doesn't exist"); rmdir(LDPath.c_str()); return false; @@ -33,7 +34,8 @@ bool SanityCheckPath(std::string const &LDPath) { bool CheckLockExists(std::string const LockPath) { // If the lock file for a squashfs path exists the we can try // to open it and ref counting will keep it alive - if (std::filesystem::exists(LockPath)) { + std::error_code ec{}; + if (std::filesystem::exists(LockPath, ec)) { SquashFSLock.open(LockPath, std::ios_base::in | std::ios_base::binary); if (SquashFSLock.is_open()) { // We managed to open the file. Which means the mount application has now refcounted our interaction with it diff --git a/Source/Linux/Utils/ELFContainer.cpp b/Source/Linux/Utils/ELFContainer.cpp index aa9330b7b..f57b1cfc0 100644 --- a/Source/Linux/Utils/ELFContainer.cpp +++ b/Source/Linux/Utils/ELFContainer.cpp @@ -95,11 +95,12 @@ ELFContainer::ELFContainer(std::string const &Filename, std::string const &RootF RawString = &RawFile.at(InterpreterHeader._64->p_offset); } std::string RootFSLink = RootFS + RawString; - while (std::filesystem::is_symlink(RootFSLink)) { + std::error_code ec{}; + while (std::filesystem::is_symlink(RootFSLink, ec)) { // Do some special handling if the RootFS's linker is a symlink // Ubuntu's rootFS by default provides an absolute location symlink to the linker // Resolve this around back to the rootfs - auto SymlinkTarget = std::filesystem::read_symlink(RootFSLink); + auto SymlinkTarget = std::filesystem::read_symlink(RootFSLink, ec); if (SymlinkTarget.is_absolute()) { RootFSLink = RootFS + SymlinkTarget.string(); } diff --git a/Source/Tests/FEXLoader.cpp b/Source/Tests/FEXLoader.cpp index d8f059cc5..3d457b5b3 100644 --- a/Source/Tests/FEXLoader.cpp +++ b/Source/Tests/FEXLoader.cpp @@ -39,6 +39,7 @@ $end_info$ namespace { static bool SilentLog; static int OutputFD {STDERR_FILENO}; +static bool ExecutedWithFD {false}; void MsgHandler(LogMan::DebugLevels Level, char const *Message) { const char *CharLevel{nullptr}; @@ -163,8 +164,12 @@ bool RanAsInterpreter(char *Program) { bool IsInterpreterInstalled() { // The interpreter is installed if both the binfmt_misc handlers are available - return std::filesystem::exists("/proc/sys/fs/binfmt_misc/FEX-x86") && - std::filesystem::exists("/proc/sys/fs/binfmt_misc/FEX-x86_64"); + // Or if we were originally executed with FD. Which means the interpreter is installed + + std::error_code ec{}; + return ExecutedWithFD || + (std::filesystem::exists("/proc/sys/fs/binfmt_misc/FEX-x86", ec) && + std::filesystem::exists("/proc/sys/fs/binfmt_misc/FEX-x86_64", ec)); } void AOTGenSection(FEXCore::Context::Context *CTX, ELFCodeLoader2::LoadedSection &Section) { @@ -317,6 +322,9 @@ void AOTGenSection(FEXCore::Context::Context *CTX, ELFCodeLoader2::LoadedSection int main(int argc, char **argv, char **const envp) { bool IsInterpreter = RanAsInterpreter(argv[0]); + + ExecutedWithFD = getauxval(AT_EXECFD) != 0; + LogMan::Throw::InstallHandler(AssertHandler); LogMan::Msg::InstallHandler(MsgHandler); @@ -403,7 +411,8 @@ int main(int argc, char **argv, char **const envp) { InterpreterHandler(&Program, LDPath(), &Args); - if (!std::filesystem::exists(Program)) { + std::error_code ec{}; + if (!std::filesystem::exists(Program, ec)) { // Early exit if the program passed in doesn't exist // Will prevent a crash later fprintf(stderr, "%s: command not found\n", Program.c_str()); @@ -542,16 +551,16 @@ int main(int argc, char **argv, char **const envp) { FEXCore::Context::RunUntilExit(CTX); } - std::filesystem::create_directories(std::filesystem::path(FEXCore::Config::GetDataDirectory()) / "aotir"); - - FEXCore::Context::WriteFilesWithCode(CTX, [](const std::string& fileid, const std::string& filename) { - auto filepath = std::filesystem::path(FEXCore::Config::GetDataDirectory()) / "aotir" / (fileid + ".path"); - int fd = open(filepath.c_str(), O_CREAT | O_EXCL | O_WRONLY, 0644); - if (fd != -1) { - write(fd, filename.c_str(), filename.size()); - close(fd); - } - }); + if (std::filesystem::create_directories(std::filesystem::path(FEXCore::Config::GetDataDirectory()) / "aotir", ec)) { + FEXCore::Context::WriteFilesWithCode(CTX, [](const std::string& fileid, const std::string& filename) { + auto filepath = std::filesystem::path(FEXCore::Config::GetDataDirectory()) / "aotir" / (fileid + ".path"); + int fd = open(filepath.c_str(), O_CREAT | O_EXCL | O_WRONLY, 0644); + if (fd != -1) { + write(fd, filename.c_str(), filename.size()); + close(fd); + } + }); + } if (AOTIRCapture() || AOTIRGenerate()) { diff --git a/Source/Tools/FEXConfig/Main.cpp b/Source/Tools/FEXConfig/Main.cpp index 7d53448a2..29142985c 100644 --- a/Source/Tools/FEXConfig/Main.cpp +++ b/Source/Tools/FEXConfig/Main.cpp @@ -77,7 +77,8 @@ namespace { } bool OpenFile(std::string Filename, bool LoadDefault = false) { - if (!std::filesystem::exists(Filename)) { + std::error_code ec{}; + if (!std::filesystem::exists(Filename, ec)) { if (LoadDefault) { LoadDefaultSettings(); ConfigFilename = Filename; @@ -98,9 +99,10 @@ namespace { std::scoped_lock lk{NamedRootFSUpdator}; NamedRootFS.clear(); std::string RootFS = FEXCore::Config::GetDataDirectory() + "RootFS/"; - if (!std::filesystem::exists(RootFS)) { + std::error_code ec{}; + if (!std::filesystem::exists(RootFS, ec)) { // Doesn't exist, create the the folder as a user convenience - if (!std::filesystem::create_directories(RootFS)) { + if (!std::filesystem::create_directories(RootFS, ec)) { // Well I guess we failed return; }