Skip to content

Commit

Permalink
Merge pull request #1192 from Sonicadvance1/workaround_static_pie
Browse files Browse the repository at this point in the history
AArch64: Workaround static-pie crashing
  • Loading branch information
Sonicadvance1 authored Aug 3, 2021
2 parents ff98a43 + b586592 commit 4c43151
Show file tree
Hide file tree
Showing 7 changed files with 123 additions and 55 deletions.
93 changes: 71 additions & 22 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -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")
Expand All @@ -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
Expand Down Expand Up @@ -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()
Expand Down Expand Up @@ -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/)

Expand Down
5 changes: 3 additions & 2 deletions External/FEXCore/Source/Common/Paths.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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());
}
}
Expand Down
26 changes: 15 additions & 11 deletions External/FEXCore/Source/Interface/Config/Config.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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 "./";
}
Expand All @@ -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";
Expand All @@ -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";
}
Expand Down Expand Up @@ -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;
}
}
Expand Down Expand Up @@ -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);
}
}
Expand All @@ -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);
}
}
Expand Down
6 changes: 4 additions & 2 deletions Source/Common/RootFSSetup.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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
Expand Down
5 changes: 3 additions & 2 deletions Source/Linux/Utils/ELFContainer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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();
}
Expand Down
35 changes: 22 additions & 13 deletions Source/Tests/FEXLoader.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ desc: Glues the ELF loader, FEXCore and LinuxSyscalls to launch an elf under fex
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};
Expand Down Expand Up @@ -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) {
Expand Down Expand Up @@ -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);

Expand Down Expand Up @@ -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());
Expand Down Expand Up @@ -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()) {

Expand Down
8 changes: 5 additions & 3 deletions Source/Tools/FEXConfig/Main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -98,9 +99,10 @@ namespace {
std::scoped_lock<std::mutex> 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;
}
Expand Down

0 comments on commit 4c43151

Please sign in to comment.