mirror of
https://github.com/FEX-Emu/FEX.git
synced 2024-12-15 01:49:00 +00:00
Merge pull request #2549 from Sonicadvance1/glibc_remaining_allocations
Move FEX away from the remaining glibc allocations that we can
This commit is contained in:
commit
aac4e25ca4
2
.gitmodules
vendored
2
.gitmodules
vendored
@ -3,7 +3,7 @@
|
||||
path = External/vixl
|
||||
url = https://github.com/FEX-Emu/vixl.git
|
||||
[submodule "External/cpp-optparse"]
|
||||
path = External/cpp-optparse
|
||||
path = Source/Common/cpp-optparse
|
||||
url = https://github.com/Sonicadvance1/cpp-optparse
|
||||
[submodule "External/imgui"]
|
||||
path = External/imgui
|
||||
|
@ -33,6 +33,7 @@ option(ENABLE_VIXL_DISASSEMBLER "Enables debug disassembler output with VIXL" FA
|
||||
option(COMPILE_VIXL_DISASSEMBLER "Compiles the vixl disassembler in to vixl" FALSE)
|
||||
option(ENABLE_FEXCORE_PROFILER "Enables use of the FEXCore timeline profiling capabilities" FALSE)
|
||||
set (FEXCORE_PROFILER_BACKEND "gpuvis" CACHE STRING "Set which backend you want to use for the FEXCore profiler")
|
||||
option(ENABLE_GLIBC_ALLOCATOR_HOOK_FAULT "Enables glibc memory allocation hooking with fault for CI testing")
|
||||
|
||||
set (X86_32_TOOLCHAIN_FILE "${CMAKE_CURRENT_SOURCE_DIR}/toolchain_x86_32.cmake" CACHE FILEPATH "Toolchain file for the (cross-)compiler targeting i686")
|
||||
set (X86_64_TOOLCHAIN_FILE "${CMAKE_CURRENT_SOURCE_DIR}/toolchain_x86_64.cmake" CACHE FILEPATH "Toolchain file for the (cross-)compiler targeting x86_64")
|
||||
@ -56,6 +57,10 @@ if (ENABLE_FEXCORE_PROFILER)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if (ENABLE_GLIBC_ALLOCATOR_HOOK_FAULT)
|
||||
add_definitions(-DGLIBC_ALLOCATOR_FAULT=1)
|
||||
endif()
|
||||
|
||||
# uninstall target
|
||||
if(NOT TARGET uninstall)
|
||||
configure_file(
|
||||
@ -237,9 +242,6 @@ if (BUILD_TESTS)
|
||||
include(Catch)
|
||||
endif()
|
||||
|
||||
add_subdirectory(External/cpp-optparse/)
|
||||
include_directories(External/cpp-optparse/)
|
||||
|
||||
add_subdirectory(External/fmt/)
|
||||
|
||||
add_subdirectory(External/imgui/)
|
||||
|
2
External/FEXCore/Scripts/config_generator.py
vendored
2
External/FEXCore/Scripts/config_generator.py
vendored
@ -387,7 +387,7 @@ def print_parse_argloader_options(options):
|
||||
output_argloader.write("\t}\n")
|
||||
else:
|
||||
if (NeedsString):
|
||||
output_argloader.write("\tfextl::string UserValue = fextl::string_from_string(Options[\"{0}\"]);\n".format(op_key))
|
||||
output_argloader.write("\tfextl::string UserValue = Options[\"{0}\"];\n".format(op_key))
|
||||
else:
|
||||
output_argloader.write("\t{0} UserValue = Options.get(\"{1}\");\n".format(value_type, op_key))
|
||||
|
||||
|
5
External/FEXCore/Source/CMakeLists.txt
vendored
5
External/FEXCore/Source/CMakeLists.txt
vendored
@ -146,6 +146,11 @@ set (SRCS
|
||||
Utils/Profiler.cpp
|
||||
)
|
||||
|
||||
if (ENABLE_GLIBC_ALLOCATOR_HOOK_FAULT)
|
||||
list(APPEND FEXCORE_BASE_SRCS
|
||||
Utils/AllocatorOverride.cpp)
|
||||
endif()
|
||||
|
||||
if (ENABLE_INTERPRETER)
|
||||
list(APPEND SRCS
|
||||
Interface/Core/Interpreter/InterpreterCore.cpp
|
||||
|
35
External/FEXCore/Source/Common/Paths.cpp
vendored
35
External/FEXCore/Source/Common/Paths.cpp
vendored
@ -1,17 +1,21 @@
|
||||
#include "Common/Paths.h"
|
||||
#include <FEXCore/Utils/Allocator.h>
|
||||
#include <FEXCore/Utils/LogManager.h>
|
||||
#include <FEXCore/fextl/memory.h>
|
||||
#include <FEXCore/fextl/string.h>
|
||||
#include <FEXHeaderUtils/Filesystem.h>
|
||||
|
||||
#include <cstdlib>
|
||||
#include <filesystem>
|
||||
#include <memory>
|
||||
#include <pwd.h>
|
||||
#include <system_error>
|
||||
#include <sys/stat.h>
|
||||
#include <unistd.h>
|
||||
|
||||
namespace FEXCore::Paths {
|
||||
std::unique_ptr<fextl::string> CachePath;
|
||||
std::unique_ptr<fextl::string> EntryCache;
|
||||
fextl::string CachePath{};
|
||||
fextl::string EntryCache{};
|
||||
|
||||
char const* FindUserHomeThroughUID() {
|
||||
auto passwd = getpwuid(geteuid());
|
||||
@ -43,9 +47,6 @@ namespace FEXCore::Paths {
|
||||
}
|
||||
|
||||
void InitializePaths() {
|
||||
CachePath = std::make_unique<fextl::string>();
|
||||
EntryCache = std::make_unique<fextl::string>();
|
||||
|
||||
char const *HomeDir = getenv("HOME");
|
||||
|
||||
if (!HomeDir) {
|
||||
@ -58,35 +59,29 @@ namespace FEXCore::Paths {
|
||||
|
||||
char *XDGDataDir = getenv("XDG_DATA_DIR");
|
||||
if (XDGDataDir) {
|
||||
*CachePath = XDGDataDir;
|
||||
CachePath = XDGDataDir;
|
||||
}
|
||||
else {
|
||||
if (HomeDir) {
|
||||
*CachePath = HomeDir;
|
||||
CachePath = HomeDir;
|
||||
}
|
||||
}
|
||||
|
||||
*CachePath += "/.fex-emu/";
|
||||
*EntryCache = *CachePath + "/EntryCache/";
|
||||
CachePath += "/.fex-emu/";
|
||||
EntryCache = CachePath + "/EntryCache/";
|
||||
|
||||
std::error_code ec{};
|
||||
// Ensure the folder structure is created for our Data
|
||||
if (!std::filesystem::exists(*EntryCache, ec) &&
|
||||
!std::filesystem::create_directories(*EntryCache, ec)) {
|
||||
LogMan::Msg::DFmt("Couldn't create EntryCache directory: '{}'", *EntryCache);
|
||||
if (!FHU::Filesystem::Exists(EntryCache) &&
|
||||
!FHU::Filesystem::CreateDirectories(EntryCache)) {
|
||||
LogMan::Msg::DFmt("Couldn't create EntryCache directory: '{}'", EntryCache);
|
||||
}
|
||||
}
|
||||
|
||||
void ShutdownPaths() {
|
||||
CachePath.reset();
|
||||
EntryCache.reset();
|
||||
}
|
||||
|
||||
fextl::string GetCachePath() {
|
||||
return *CachePath;
|
||||
return CachePath;
|
||||
}
|
||||
|
||||
fextl::string GetEntryCachePath() {
|
||||
return *EntryCache;
|
||||
return EntryCache;
|
||||
}
|
||||
}
|
||||
|
@ -4,13 +4,16 @@
|
||||
#include "Utils/FileLoading.h"
|
||||
|
||||
#include <FEXCore/Config/Config.h>
|
||||
#include <FEXCore/Utils/Allocator.h>
|
||||
#include <FEXCore/Utils/CPUInfo.h>
|
||||
#include <FEXCore/Utils/LogManager.h>
|
||||
#include <FEXCore/fextl/list.h>
|
||||
#include <FEXCore/fextl/map.h>
|
||||
#include <FEXCore/fextl/memory.h>
|
||||
#include <FEXCore/fextl/string.h>
|
||||
#include <FEXCore/fextl/unordered_map.h>
|
||||
#include <FEXCore/fextl/vector.h>
|
||||
#include <FEXHeaderUtils/Filesystem.h>
|
||||
|
||||
#include <array>
|
||||
#include <assert.h>
|
||||
@ -18,7 +21,7 @@
|
||||
#include <filesystem>
|
||||
#include <fstream>
|
||||
#include <functional>
|
||||
#include <memory>
|
||||
#include <linux/limits.h>
|
||||
#include <optional>
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
@ -45,13 +48,13 @@ namespace DefaultValues {
|
||||
namespace JSON {
|
||||
struct JsonAllocator {
|
||||
jsonPool_t PoolObject;
|
||||
std::unique_ptr<fextl::list<json_t>> json_objects;
|
||||
fextl::unique_ptr<fextl::list<json_t>> json_objects;
|
||||
};
|
||||
static_assert(offsetof(JsonAllocator, PoolObject) == 0, "This needs to be at offset zero");
|
||||
|
||||
json_t* PoolInit(jsonPool_t* Pool) {
|
||||
JsonAllocator* alloc = reinterpret_cast<JsonAllocator*>(Pool);
|
||||
alloc->json_objects = std::make_unique<fextl::list<json_t>>();
|
||||
alloc->json_objects = fextl::make_unique<fextl::list<json_t>>();
|
||||
return &*alloc->json_objects->emplace(alloc->json_objects->end());
|
||||
}
|
||||
|
||||
@ -143,9 +146,8 @@ namespace JSON {
|
||||
}
|
||||
|
||||
// Ensure the folder structure is created for our configuration
|
||||
std::error_code ec{};
|
||||
if (!std::filesystem::exists(ConfigDir, ec) &&
|
||||
!std::filesystem::create_directories(ConfigDir, ec)) {
|
||||
if (!FHU::Filesystem::Exists(ConfigDir) &&
|
||||
!FHU::Filesystem::CreateDirectories(ConfigDir)) {
|
||||
// Let's go local in this case
|
||||
return "./";
|
||||
}
|
||||
@ -175,10 +177,9 @@ namespace JSON {
|
||||
fextl::string GetApplicationConfig(const fextl::string &Filename, bool Global) {
|
||||
fextl::string ConfigFile = GetConfigDirectory(Global);
|
||||
|
||||
std::error_code ec{};
|
||||
if (!Global &&
|
||||
!std::filesystem::exists(ConfigFile, ec) &&
|
||||
!std::filesystem::create_directories(ConfigFile, ec)) {
|
||||
!FHU::Filesystem::Exists(ConfigFile) &&
|
||||
!FHU::Filesystem::CreateDirectories(ConfigFile)) {
|
||||
LogMan::Msg::DFmt("Couldn't create config directory: '{}'", ConfigFile);
|
||||
// Let's go local in this case
|
||||
return "./" + Filename + ".json";
|
||||
@ -188,8 +189,8 @@ namespace JSON {
|
||||
|
||||
// Attempt to create the local folder if it doesn't exist
|
||||
if (!Global &&
|
||||
!std::filesystem::exists(ConfigFile, ec) &&
|
||||
!std::filesystem::create_directories(ConfigFile, ec)) {
|
||||
!FHU::Filesystem::Exists(ConfigFile) &&
|
||||
!FHU::Filesystem::CreateDirectories(ConfigFile)) {
|
||||
// Let's go local in this case
|
||||
return "./" + Filename + ".json";
|
||||
}
|
||||
@ -208,7 +209,7 @@ namespace JSON {
|
||||
return 0;
|
||||
}
|
||||
|
||||
static fextl::map<FEXCore::Config::LayerType, std::unique_ptr<FEXCore::Config::Layer>> ConfigLayers;
|
||||
static fextl::map<FEXCore::Config::LayerType, fextl::unique_ptr<FEXCore::Config::Layer>> ConfigLayers;
|
||||
static FEXCore::Config::Layer *Meta{};
|
||||
|
||||
constexpr std::array<FEXCore::Config::LayerType, 9> LoadOrder = {
|
||||
@ -311,7 +312,7 @@ namespace JSON {
|
||||
}
|
||||
|
||||
void Initialize() {
|
||||
AddLayer(std::make_unique<MetaLayer>(FEXCore::Config::LayerType::LAYER_TOP));
|
||||
AddLayer(fextl::make_unique<MetaLayer>(FEXCore::Config::LayerType::LAYER_TOP));
|
||||
Meta = ConfigLayers.begin()->second.get();
|
||||
}
|
||||
|
||||
@ -334,10 +335,9 @@ namespace JSON {
|
||||
return {};
|
||||
}
|
||||
|
||||
std::filesystem::path Path{PathName};
|
||||
|
||||
// Expand home if it exists
|
||||
if (Path.is_relative()) {
|
||||
if (FHU::Filesystem::IsRelative(PathName)) {
|
||||
fextl::string Home = getenv("HOME") ?: "";
|
||||
// Home expansion only works if it is the first character
|
||||
// This matches bash behaviour
|
||||
@ -347,12 +347,15 @@ namespace JSON {
|
||||
}
|
||||
|
||||
// Expand relative path to absolute
|
||||
Path = std::filesystem::absolute(Path);
|
||||
char ExistsTempPath[PATH_MAX];
|
||||
char *RealPath = realpath(PathName.c_str(), ExistsTempPath);
|
||||
if (RealPath) {
|
||||
PathName = RealPath;
|
||||
}
|
||||
|
||||
// Only return if it exists
|
||||
std::error_code ec{};
|
||||
if (std::filesystem::exists(Path, ec)) {
|
||||
return fextl::string_from_path(Path);
|
||||
if (FHU::Filesystem::Exists(PathName)) {
|
||||
return PathName;
|
||||
}
|
||||
}
|
||||
else {
|
||||
@ -368,9 +371,9 @@ namespace JSON {
|
||||
// HostThunks: $CMAKE_INSTALL_PREFIX/lib/fex-emu/HostThunks/
|
||||
// GuestThunks: $CMAKE_INSTALL_PREFIX/share/fex-emu/GuestThunks/
|
||||
if (!ContainerPrefix.empty() && !PathName.empty()) {
|
||||
if (!std::filesystem::exists(PathName)) {
|
||||
if (!FHU::Filesystem::Exists(PathName)) {
|
||||
auto ContainerPath = ContainerPrefix + PathName;
|
||||
if (std::filesystem::exists(ContainerPath)) {
|
||||
if (FHU::Filesystem::Exists(ContainerPath)) {
|
||||
return ContainerPath;
|
||||
}
|
||||
}
|
||||
@ -379,11 +382,11 @@ namespace JSON {
|
||||
return {};
|
||||
}
|
||||
|
||||
constexpr char ContainerManager[] = "/run/host/container-manager";
|
||||
|
||||
fextl::string FindContainer() {
|
||||
// We only support pressure-vessel at the moment
|
||||
const static fextl::string ContainerManager = "/run/host/container-manager";
|
||||
if (std::filesystem::exists(ContainerManager)) {
|
||||
if (FHU::Filesystem::Exists(ContainerManager)) {
|
||||
fextl::vector<char> Manager{};
|
||||
if (FEXCore::FileLoading::LoadFile(Manager, ContainerManager)) {
|
||||
// Trim the whitespace, may contain a newline
|
||||
@ -397,8 +400,7 @@ namespace JSON {
|
||||
|
||||
fextl::string FindContainerPrefix() {
|
||||
// We only support pressure-vessel at the moment
|
||||
const static fextl::string ContainerManager = "/run/host/container-manager";
|
||||
if (std::filesystem::exists(ContainerManager)) {
|
||||
if (FHU::Filesystem::Exists(ContainerManager)) {
|
||||
fextl::vector<char> Manager{};
|
||||
if (FEXCore::FileLoading::LoadFile(Manager, ContainerManager)) {
|
||||
// Trim the whitespace, may contain a newline
|
||||
@ -467,7 +469,7 @@ namespace JSON {
|
||||
|
||||
if (FEXCore::Config::Exists(FEXCore::Config::CONFIG_ROOTFS)) {
|
||||
FEX_CONFIG_OPT(PathName, ROOTFS);
|
||||
auto ExpandedString = ExpandPath(ContainerPrefix, PathName());
|
||||
auto ExpandedString = ExpandPath(ContainerPrefix,PathName());
|
||||
if (!ExpandedString.empty()) {
|
||||
// Adjust the path if it ended up being relative
|
||||
FEXCore::Config::EraseSet(FEXCore::Config::CONFIG_ROOTFS, ExpandedString);
|
||||
@ -518,7 +520,7 @@ namespace JSON {
|
||||
}
|
||||
}
|
||||
|
||||
void AddLayer(std::unique_ptr<FEXCore::Config::Layer> _Layer) {
|
||||
void AddLayer(fextl::unique_ptr<FEXCore::Config::Layer> _Layer) {
|
||||
ConfigLayers.emplace(_Layer->GetLayerType(), std::move(_Layer));
|
||||
}
|
||||
|
||||
@ -705,7 +707,8 @@ namespace JSON {
|
||||
}
|
||||
|
||||
void EnvLoader::Load() {
|
||||
fextl::unordered_map<std::string_view, std::string_view> EnvMap;
|
||||
using EnvMapType = fextl::unordered_map<std::string_view, std::string_view>;
|
||||
EnvMapType EnvMap;
|
||||
|
||||
for(const char *const *pvar=envp; pvar && *pvar; pvar++) {
|
||||
std::string_view Var(*pvar);
|
||||
@ -719,10 +722,10 @@ namespace JSON {
|
||||
#define ENVLOADER
|
||||
#include <FEXCore/Config/ConfigOptions.inl>
|
||||
|
||||
EnvMap[Key]=Value;
|
||||
EnvMap[Key] = Value;
|
||||
}
|
||||
|
||||
std::function GetVar = [=](const std::string_view id) -> std::optional<std::string_view> {
|
||||
auto GetVar = [](EnvMapType &EnvMap, const std::string_view id) -> std::optional<std::string_view> {
|
||||
if (EnvMap.find(id) != EnvMap.end())
|
||||
return EnvMap.at(id);
|
||||
|
||||
@ -739,31 +742,31 @@ namespace JSON {
|
||||
std::optional<std::string_view> Value;
|
||||
|
||||
for (auto &it : EnvConfigLookup) {
|
||||
if ((Value = GetVar(it.first)).has_value()) {
|
||||
if ((Value = GetVar(EnvMap, it.first)).has_value()) {
|
||||
Set(it.second, fextl::string(*Value));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
std::unique_ptr<FEXCore::Config::Layer> CreateGlobalMainLayer() {
|
||||
return std::make_unique<FEXCore::Config::MainLoader>(FEXCore::Config::LayerType::LAYER_GLOBAL_MAIN);
|
||||
fextl::unique_ptr<FEXCore::Config::Layer> CreateGlobalMainLayer() {
|
||||
return fextl::make_unique<FEXCore::Config::MainLoader>(FEXCore::Config::LayerType::LAYER_GLOBAL_MAIN);
|
||||
}
|
||||
|
||||
std::unique_ptr<FEXCore::Config::Layer> CreateMainLayer(fextl::string const *File) {
|
||||
fextl::unique_ptr<FEXCore::Config::Layer> CreateMainLayer(fextl::string const *File) {
|
||||
if (File) {
|
||||
return std::make_unique<FEXCore::Config::MainLoader>(*File);
|
||||
return fextl::make_unique<FEXCore::Config::MainLoader>(*File);
|
||||
}
|
||||
else {
|
||||
return std::make_unique<FEXCore::Config::MainLoader>(FEXCore::Config::LayerType::LAYER_MAIN);
|
||||
return fextl::make_unique<FEXCore::Config::MainLoader>(FEXCore::Config::LayerType::LAYER_MAIN);
|
||||
}
|
||||
}
|
||||
|
||||
std::unique_ptr<FEXCore::Config::Layer> CreateAppLayer(const fextl::string& Filename, FEXCore::Config::LayerType Type) {
|
||||
return std::make_unique<FEXCore::Config::AppLoader>(Filename, Type);
|
||||
fextl::unique_ptr<FEXCore::Config::Layer> CreateAppLayer(const fextl::string& Filename, FEXCore::Config::LayerType Type) {
|
||||
return fextl::make_unique<FEXCore::Config::AppLoader>(Filename, Type);
|
||||
}
|
||||
|
||||
std::unique_ptr<FEXCore::Config::Layer> CreateEnvironmentLayer(char *const _envp[]) {
|
||||
return std::make_unique<FEXCore::Config::EnvLoader>(_envp);
|
||||
fextl::unique_ptr<FEXCore::Config::Layer> CreateEnvironmentLayer(char *const _envp[]) {
|
||||
return fextl::make_unique<FEXCore::Config::EnvLoader>(_envp);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -24,10 +24,6 @@ namespace FEXCore::Context {
|
||||
IR::InstallOpcodeHandlers(Mode);
|
||||
}
|
||||
|
||||
void ShutdownStaticTables() {
|
||||
FEXCore::Paths::ShutdownPaths();
|
||||
}
|
||||
|
||||
FEXCore::Context::Context *FEXCore::Context::Context::CreateNewContext() {
|
||||
return new FEXCore::Context::ContextImpl{};
|
||||
}
|
||||
|
@ -15,6 +15,7 @@
|
||||
#include <FEXCore/Debug/InternalThreadState.h>
|
||||
#include <FEXCore/Utils/CompilerDefs.h>
|
||||
#include <FEXCore/Utils/Event.h>
|
||||
#include <FEXCore/fextl/memory.h>
|
||||
#include <FEXCore/fextl/set.h>
|
||||
#include <FEXCore/fextl/string.h>
|
||||
#include <FEXCore/fextl/unordered_map.h>
|
||||
@ -261,14 +262,14 @@ namespace FEXCore::Context {
|
||||
FEXCore::CPUIDEmu CPUID;
|
||||
FEXCore::HLE::SyscallHandler *SyscallHandler{};
|
||||
FEXCore::HLE::SourcecodeResolver *SourcecodeResolver{};
|
||||
std::unique_ptr<FEXCore::ThunkHandler> ThunkHandler;
|
||||
std::unique_ptr<FEXCore::CPU::Dispatcher> Dispatcher;
|
||||
fextl::unique_ptr<FEXCore::ThunkHandler> ThunkHandler;
|
||||
fextl::unique_ptr<FEXCore::CPU::Dispatcher> Dispatcher;
|
||||
|
||||
CustomCPUFactoryType CustomCPUFactory;
|
||||
FEXCore::Context::ExitHandler CustomExitHandler;
|
||||
|
||||
#ifdef BLOCKSTATS
|
||||
std::unique_ptr<FEXCore::BlockSamplingData> BlockData;
|
||||
fextl::unique_ptr<FEXCore::BlockSamplingData> BlockData;
|
||||
#endif
|
||||
|
||||
SignalDelegator *SignalDelegation{};
|
||||
@ -405,10 +406,10 @@ namespace FEXCore::Context {
|
||||
|
||||
// Entry Cache
|
||||
std::mutex ExitMutex;
|
||||
std::unique_ptr<GdbServer> DebugServer;
|
||||
fextl::unique_ptr<GdbServer> DebugServer;
|
||||
|
||||
IR::AOTIRCaptureCache IRCaptureCache;
|
||||
std::unique_ptr<FEXCore::CodeSerialize::CodeObjectSerializeService> CodeObjectCacheService;
|
||||
fextl::unique_ptr<FEXCore::CodeSerialize::CodeObjectSerializeService> CodeObjectCacheService;
|
||||
|
||||
bool StartPaused = false;
|
||||
bool IsMemoryShared = false;
|
||||
|
16
External/FEXCore/Source/Interface/Core/Core.cpp
vendored
16
External/FEXCore/Source/Interface/Core/Core.cpp
vendored
@ -45,6 +45,7 @@ $end_info$
|
||||
#include <FEXCore/Utils/LogManager.h>
|
||||
#include <FEXCore/Utils/Threads.h>
|
||||
#include <FEXCore/Utils/Profiler.h>
|
||||
#include <FEXCore/fextl/memory.h>
|
||||
#include <FEXCore/fextl/set.h>
|
||||
#include <FEXCore/fextl/sstream.h>
|
||||
#include <FEXCore/fextl/vector.h>
|
||||
@ -59,7 +60,6 @@ $end_info$
|
||||
#include <filesystem>
|
||||
#include <functional>
|
||||
#include <fstream>
|
||||
#include <memory>
|
||||
#include <mutex>
|
||||
#include <queue>
|
||||
#include <shared_mutex>
|
||||
@ -151,7 +151,7 @@ namespace FEXCore::Context {
|
||||
BlockData = std::make_unique<FEXCore::BlockSamplingData>();
|
||||
#endif
|
||||
if (Config.CacheObjectCodeCompilation() != FEXCore::Config::ConfigObjectCodeHandler::CONFIG_NONE) {
|
||||
CodeObjectCacheService = std::make_unique<FEXCore::CodeSerialize::CodeObjectSerializeService>(this);
|
||||
CodeObjectCacheService = fextl::make_unique<FEXCore::CodeSerialize::CodeObjectSerializeService>(this);
|
||||
}
|
||||
if (!Config.EnableAVX) {
|
||||
HostFeatures.SupportsAVX = false;
|
||||
@ -275,7 +275,7 @@ namespace FEXCore::Context {
|
||||
StopGdbServer();
|
||||
}
|
||||
|
||||
ThunkHandler.reset(FEXCore::ThunkHandler::Create());
|
||||
ThunkHandler = FEXCore::ThunkHandler::Create();
|
||||
|
||||
using namespace FEXCore::Core;
|
||||
|
||||
@ -295,7 +295,7 @@ namespace FEXCore::Context {
|
||||
|
||||
void ContextImpl::StartGdbServer() {
|
||||
if (!DebugServer) {
|
||||
DebugServer = std::make_unique<GdbServer>(this);
|
||||
DebugServer = fextl::make_unique<GdbServer>(this);
|
||||
StartPaused = true;
|
||||
}
|
||||
}
|
||||
@ -557,11 +557,11 @@ namespace FEXCore::Context {
|
||||
}
|
||||
|
||||
void ContextImpl::InitializeCompiler(FEXCore::Core::InternalThreadState* Thread) {
|
||||
Thread->OpDispatcher = std::make_unique<FEXCore::IR::OpDispatchBuilder>(this);
|
||||
Thread->OpDispatcher = fextl::make_unique<FEXCore::IR::OpDispatchBuilder>(this);
|
||||
Thread->OpDispatcher->SetMultiblock(Config.Multiblock);
|
||||
Thread->LookupCache = std::make_unique<FEXCore::LookupCache>(this);
|
||||
Thread->FrontendDecoder = std::make_unique<FEXCore::Frontend::Decoder>(this);
|
||||
Thread->PassManager = std::make_unique<FEXCore::IR::PassManager>();
|
||||
Thread->LookupCache = fextl::make_unique<FEXCore::LookupCache>(this);
|
||||
Thread->FrontendDecoder = fextl::make_unique<FEXCore::Frontend::Decoder>(this);
|
||||
Thread->PassManager = fextl::make_unique<FEXCore::IR::PassManager>();
|
||||
Thread->PassManager->RegisterExitHandler([this]() {
|
||||
Stop(false /* Ignore current thread */);
|
||||
});
|
||||
|
@ -12,6 +12,7 @@
|
||||
#include <FEXCore/Core/CoreState.h>
|
||||
#include <FEXCore/Core/X86Enums.h>
|
||||
#include <FEXCore/Debug/InternalThreadState.h>
|
||||
#include <FEXCore/fextl/memory.h>
|
||||
#include <FEXHeaderUtils/Syscalls.h>
|
||||
|
||||
#include <array>
|
||||
@ -672,8 +673,8 @@ void Arm64Dispatcher::InitThreadPointers(FEXCore::Core::InternalThreadState *Thr
|
||||
}
|
||||
}
|
||||
|
||||
std::unique_ptr<Dispatcher> Dispatcher::CreateArm64(FEXCore::Context::ContextImpl *CTX, const DispatcherConfig &Config) {
|
||||
return std::make_unique<Arm64Dispatcher>(CTX, Config);
|
||||
fextl::unique_ptr<Dispatcher> Dispatcher::CreateArm64(FEXCore::Context::ContextImpl *CTX, const DispatcherConfig &Config) {
|
||||
return fextl::make_unique<Arm64Dispatcher>(CTX, Config);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -1,6 +1,7 @@
|
||||
#pragma once
|
||||
|
||||
#include <FEXCore/Core/CPUBackend.h>
|
||||
#include <FEXCore/fextl/memory.h>
|
||||
#include "Interface/Core/ArchHelpers/MContext.h"
|
||||
|
||||
#include <cstdint>
|
||||
@ -73,8 +74,8 @@ public:
|
||||
virtual size_t GenerateGDBPauseCheck(uint8_t *CodeBuffer, uint64_t GuestRIP) = 0;
|
||||
virtual size_t GenerateInterpreterTrampoline(uint8_t *CodeBuffer) = 0;
|
||||
|
||||
static std::unique_ptr<Dispatcher> CreateX86(FEXCore::Context::ContextImpl *CTX, const DispatcherConfig &Config);
|
||||
static std::unique_ptr<Dispatcher> CreateArm64(FEXCore::Context::ContextImpl *CTX, const DispatcherConfig &Config);
|
||||
static fextl::unique_ptr<Dispatcher> CreateX86(FEXCore::Context::ContextImpl *CTX, const DispatcherConfig &Config);
|
||||
static fextl::unique_ptr<Dispatcher> CreateArm64(FEXCore::Context::ContextImpl *CTX, const DispatcherConfig &Config);
|
||||
|
||||
virtual void ExecuteDispatch(FEXCore::Core::CpuStateFrame *Frame) {
|
||||
DispatchPtr(Frame);
|
||||
|
@ -11,6 +11,7 @@
|
||||
#include <FEXCore/Core/CPUBackend.h>
|
||||
#include <FEXCore/Debug/InternalThreadState.h>
|
||||
#include <FEXCore/Utils/Allocator.h>
|
||||
#include <FEXCore/fextl/memory.h>
|
||||
#include <FEXCore/fextl/string.h>
|
||||
#include <FEXHeaderUtils/Syscalls.h>
|
||||
|
||||
@ -19,7 +20,6 @@
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
#include <sys/mman.h>
|
||||
#include <xbyak/xbyak.h>
|
||||
|
||||
#define STATE_PTR(STATE_TYPE, FIELD) \
|
||||
[STATE + offsetof(FEXCore::Core::STATE_TYPE, FIELD)]
|
||||
@ -417,13 +417,11 @@ X86Dispatcher::X86Dispatcher(FEXCore::Context::ContextImpl *ctx, const Dispatche
|
||||
|
||||
}
|
||||
|
||||
// Used by GenerateGDBPauseCheck, GenerateInterpreterTrampoline
|
||||
static thread_local Xbyak::CodeGenerator emit(1, &emit); // actual emit target set with setNewBuffer
|
||||
|
||||
size_t X86Dispatcher::GenerateGDBPauseCheck(uint8_t *CodeBuffer, uint64_t GuestRIP) {
|
||||
using namespace Xbyak;
|
||||
using namespace Xbyak::util;
|
||||
|
||||
Xbyak::CodeGenerator emit(1, &emit); // actual emit target set with setNewBuffer
|
||||
emit.setNewBuffer(CodeBuffer, MaxGDBPauseCheckSize);
|
||||
|
||||
Label RunBlock;
|
||||
@ -458,6 +456,7 @@ size_t X86Dispatcher::GenerateInterpreterTrampoline(uint8_t *CodeBuffer) {
|
||||
using namespace Xbyak;
|
||||
using namespace Xbyak::util;
|
||||
|
||||
Xbyak::CodeGenerator emit(1, &emit); // actual emit target set with setNewBuffer
|
||||
emit.setNewBuffer(CodeBuffer, MaxInterpreterTrampolineSize);
|
||||
|
||||
Label InlineIRData;
|
||||
@ -500,8 +499,8 @@ void X86Dispatcher::InitThreadPointers(FEXCore::Core::InternalThreadState *Threa
|
||||
}
|
||||
}
|
||||
|
||||
std::unique_ptr<Dispatcher> Dispatcher::CreateX86(FEXCore::Context::ContextImpl *CTX, const DispatcherConfig &Config) {
|
||||
return std::make_unique<X86Dispatcher>(CTX, Config);
|
||||
fextl::unique_ptr<Dispatcher> Dispatcher::CreateX86(FEXCore::Context::ContextImpl *CTX, const DispatcherConfig &Config) {
|
||||
return fextl::make_unique<X86Dispatcher>(CTX, Config);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -1,9 +1,23 @@
|
||||
#pragma once
|
||||
|
||||
#include <FEXCore/fextl/list.h>
|
||||
#include <FEXCore/fextl/unordered_map.h>
|
||||
#include <FEXCore/fextl/unordered_set.h>
|
||||
|
||||
#include "Interface/Core/Dispatcher/Dispatcher.h"
|
||||
|
||||
#define XBYAK64
|
||||
#define XBYAK_CUSTOM_ALLOC
|
||||
#define XBYAK_CUSTOM_MALLOC FEXCore::Allocator::malloc
|
||||
#define XBYAK_CUSTOM_FREE FEXCore::Allocator::free
|
||||
#define XBYAK_CUSTOM_SETS
|
||||
#define XBYAK_STD_UNORDERED_SET fextl::unordered_set
|
||||
#define XBYAK_STD_UNORDERED_MAP fextl::unordered_map
|
||||
#define XBYAK_STD_UNORDERED_MULTIMAP fextl::unordered_multimap
|
||||
#define XBYAK_STD_LIST fextl::list
|
||||
|
||||
#include <xbyak/xbyak.h>
|
||||
#include <xbyak/xbyak_util.h>
|
||||
|
||||
namespace FEXCore::Core {
|
||||
struct InternalThreadState;
|
||||
|
@ -9,7 +9,7 @@
|
||||
#endif
|
||||
|
||||
#ifdef _M_X86_64
|
||||
#include <xbyak/xbyak_util.h>
|
||||
#include "Interface/Core/Dispatcher/X86Dispatcher.h"
|
||||
#endif
|
||||
|
||||
namespace FEXCore {
|
||||
|
@ -10,8 +10,8 @@
|
||||
#include <FEXCore/Debug/InternalThreadState.h>
|
||||
#include <FEXCore/Utils/LogManager.h>
|
||||
#include <FEXCore/Utils/MathUtils.h>
|
||||
#include <FEXCore/fextl/memory.h>
|
||||
|
||||
#include <memory>
|
||||
#include <signal.h>
|
||||
#include <stdint.h>
|
||||
#include <utility>
|
||||
@ -103,8 +103,8 @@ void InterpreterCore::ClearCache() {
|
||||
BufferUsed = 0;
|
||||
}
|
||||
|
||||
std::unique_ptr<CPUBackend> CreateInterpreterCore(FEXCore::Context::ContextImpl *ctx, FEXCore::Core::InternalThreadState *Thread) {
|
||||
return std::make_unique<InterpreterCore>(ctx->Dispatcher.get(), Thread);
|
||||
fextl::unique_ptr<CPUBackend> CreateInterpreterCore(FEXCore::Context::ContextImpl *ctx, FEXCore::Core::InternalThreadState *Thread) {
|
||||
return fextl::make_unique<InterpreterCore>(ctx->Dispatcher.get(), Thread);
|
||||
}
|
||||
|
||||
void InitializeInterpreterSignalHandlers(FEXCore::Context::ContextImpl *CTX) {
|
||||
|
@ -1,6 +1,7 @@
|
||||
#pragma once
|
||||
|
||||
#include <memory>
|
||||
#include <FEXCore/Core/CPUBackend.h>
|
||||
#include <FEXCore/fextl/memory.h>
|
||||
|
||||
namespace FEXCore::Context {
|
||||
class ContextImpl;
|
||||
@ -14,7 +15,7 @@ namespace FEXCore::CPU {
|
||||
class CPUBackend;
|
||||
struct DispatcherConfig;
|
||||
|
||||
[[nodiscard]] std::unique_ptr<CPUBackend> CreateInterpreterCore(FEXCore::Context::ContextImpl *ctx,
|
||||
[[nodiscard]] fextl::unique_ptr<CPUBackend> CreateInterpreterCore(FEXCore::Context::ContextImpl *ctx,
|
||||
FEXCore::Core::InternalThreadState *Thread);
|
||||
void InitializeInterpreterSignalHandlers(FEXCore::Context::ContextImpl *CTX);
|
||||
CPUBackendFeatures GetInterpreterBackendFeatures();
|
||||
|
@ -1087,8 +1087,8 @@ void Arm64JITCore::ResetStack() {
|
||||
}
|
||||
}
|
||||
|
||||
std::unique_ptr<CPUBackend> CreateArm64JITCore(FEXCore::Context::ContextImpl *ctx, FEXCore::Core::InternalThreadState *Thread) {
|
||||
return std::make_unique<Arm64JITCore>(ctx, Thread);
|
||||
fextl::unique_ptr<CPUBackend> CreateArm64JITCore(FEXCore::Context::ContextImpl *ctx, FEXCore::Core::InternalThreadState *Thread) {
|
||||
return fextl::make_unique<Arm64JITCore>(ctx, Thread);
|
||||
}
|
||||
|
||||
void InitializeArm64JITSignalHandlers(FEXCore::Context::ContextImpl *CTX) {
|
||||
|
@ -1,6 +1,7 @@
|
||||
#pragma once
|
||||
|
||||
#include <memory>
|
||||
#include <FEXCore/Core/CPUBackend.h>
|
||||
#include <FEXCore/fextl/memory.h>
|
||||
|
||||
namespace FEXCore::Context {
|
||||
class ContextImpl;
|
||||
@ -13,12 +14,12 @@ struct InternalThreadState;
|
||||
namespace FEXCore::CPU {
|
||||
class CPUBackend;
|
||||
|
||||
[[nodiscard]] std::unique_ptr<CPUBackend> CreateX86JITCore(FEXCore::Context::ContextImpl *ctx,
|
||||
[[nodiscard]] fextl::unique_ptr<CPUBackend> CreateX86JITCore(FEXCore::Context::ContextImpl *ctx,
|
||||
FEXCore::Core::InternalThreadState *Thread);
|
||||
void InitializeX86JITSignalHandlers(FEXCore::Context::ContextImpl *CTX);
|
||||
CPUBackendFeatures GetX86JITBackendFeatures();
|
||||
|
||||
[[nodiscard]] std::unique_ptr<CPUBackend> CreateArm64JITCore(FEXCore::Context::ContextImpl *ctx,
|
||||
[[nodiscard]] fextl::unique_ptr<CPUBackend> CreateArm64JITCore(FEXCore::Context::ContextImpl *ctx,
|
||||
FEXCore::Core::InternalThreadState *Thread);
|
||||
void InitializeArm64JITSignalHandlers(FEXCore::Context::ContextImpl *CTX);
|
||||
CPUBackendFeatures GetArm64JITBackendFeatures();
|
||||
|
@ -5,6 +5,7 @@ $end_info$
|
||||
*/
|
||||
|
||||
#include "Interface/Core/JIT/x86_64/JITClass.h"
|
||||
#include "Interface/Core/Dispatcher/X86Dispatcher.h"
|
||||
|
||||
#include <FEXCore/IR/IR.h>
|
||||
#include <FEXCore/Utils/LogManager.h>
|
||||
@ -12,7 +13,6 @@ $end_info$
|
||||
#include <array>
|
||||
#include <stdint.h>
|
||||
#include <utility>
|
||||
#include <xbyak/xbyak.h>
|
||||
|
||||
namespace FEXCore::CPU {
|
||||
|
||||
|
@ -5,6 +5,7 @@ $end_info$
|
||||
*/
|
||||
|
||||
#include "Interface/Core/JIT/x86_64/JITClass.h"
|
||||
#include "Interface/Core/Dispatcher/X86Dispatcher.h"
|
||||
|
||||
#include <FEXCore/IR/IR.h>
|
||||
#include <FEXCore/Utils/LogManager.h>
|
||||
@ -12,7 +13,6 @@ $end_info$
|
||||
#include <array>
|
||||
#include <stdint.h>
|
||||
#include <utility>
|
||||
#include <xbyak/xbyak.h>
|
||||
|
||||
namespace FEXCore::CPU {
|
||||
#define DEF_OP(x) void X86JITCore::Op_##x(IR::IROp_Header *IROp, IR::NodeID Node)
|
||||
|
@ -7,6 +7,7 @@ $end_info$
|
||||
#include "Interface/Context/Context.h"
|
||||
#include "Interface/Core/CPUID.h"
|
||||
#include "Interface/Core/Dispatcher/Dispatcher.h"
|
||||
#include "Interface/Core/Dispatcher/X86Dispatcher.h"
|
||||
#include "Interface/Core/LookupCache.h"
|
||||
#include "Interface/Core/JIT/x86_64/JITClass.h"
|
||||
#include "Interface/HLE/Thunks/Thunks.h"
|
||||
@ -25,7 +26,6 @@ $end_info$
|
||||
#include <stdint.h>
|
||||
#include <unordered_map>
|
||||
#include <utility>
|
||||
#include <xbyak/xbyak.h>
|
||||
|
||||
namespace FEXCore::CPU {
|
||||
#define DEF_OP(x) void X86JITCore::Op_##x(IR::IROp_Header *IROp, IR::NodeID Node)
|
||||
|
@ -5,13 +5,12 @@ $end_info$
|
||||
*/
|
||||
|
||||
#include "Interface/Core/JIT/x86_64/JITClass.h"
|
||||
|
||||
#include "Interface/Core/Dispatcher/X86Dispatcher.h"
|
||||
#include <FEXCore/IR/IR.h>
|
||||
#include <FEXCore/Utils/LogManager.h>
|
||||
|
||||
#include <array>
|
||||
#include <stdint.h>
|
||||
#include <xbyak/xbyak.h>
|
||||
|
||||
namespace FEXCore::CPU {
|
||||
|
||||
|
@ -5,12 +5,11 @@ $end_info$
|
||||
*/
|
||||
|
||||
#include "Interface/Core/JIT/x86_64/JITClass.h"
|
||||
|
||||
#include "Interface/Core/Dispatcher/X86Dispatcher.h"
|
||||
#include <FEXCore/IR/IR.h>
|
||||
|
||||
#include <array>
|
||||
#include <stdint.h>
|
||||
#include <xbyak/xbyak.h>
|
||||
|
||||
namespace FEXCore::CPU {
|
||||
#define DEF_OP(x) void X86JITCore::Op_##x(IR::IROp_Header *IROp, IR::NodeID Node)
|
||||
|
@ -5,12 +5,12 @@ $end_info$
|
||||
*/
|
||||
|
||||
#include "Interface/Core/JIT/x86_64/JITClass.h"
|
||||
#include "Interface/Core/Dispatcher/X86Dispatcher.h"
|
||||
|
||||
#include <FEXCore/IR/IR.h>
|
||||
|
||||
#include <array>
|
||||
#include <stdint.h>
|
||||
#include <xbyak/xbyak.h>
|
||||
|
||||
namespace FEXCore::CPU {
|
||||
|
||||
|
@ -40,7 +40,6 @@ $end_info$
|
||||
#include <tuple>
|
||||
#include <unordered_map>
|
||||
#include <utility>
|
||||
#include <xbyak/xbyak.h>
|
||||
|
||||
// #define DEBUG_RA 1
|
||||
// #define DEBUG_CYCLES
|
||||
@ -788,8 +787,8 @@ CPUBackend::CompiledCode X86JITCore::CompileCode(uint64_t Entry, [[maybe_unused]
|
||||
return CodeData;
|
||||
}
|
||||
|
||||
std::unique_ptr<CPUBackend> CreateX86JITCore(FEXCore::Context::ContextImpl *ctx, FEXCore::Core::InternalThreadState *Thread) {
|
||||
return std::make_unique<X86JITCore>(ctx, Thread);
|
||||
fextl::unique_ptr<CPUBackend> CreateX86JITCore(FEXCore::Context::ContextImpl *ctx, FEXCore::Core::InternalThreadState *Thread) {
|
||||
return fextl::make_unique<X86JITCore>(ctx, Thread);
|
||||
}
|
||||
|
||||
CPUBackendFeatures GetX86JITBackendFeatures() {
|
||||
|
@ -9,12 +9,9 @@ $end_info$
|
||||
#include <FEXCore/IR/RegisterAllocationData.h>
|
||||
#include "Interface/Core/BlockSamplingData.h"
|
||||
#include "Interface/Core/Dispatcher/Dispatcher.h"
|
||||
#include "Interface/Core/Dispatcher/X86Dispatcher.h"
|
||||
#include "Interface/Core/ObjectCache/Relocations.h"
|
||||
|
||||
#define XBYAK64
|
||||
#include <xbyak/xbyak.h>
|
||||
#include <xbyak/xbyak_util.h>
|
||||
|
||||
using namespace Xbyak;
|
||||
|
||||
#include <FEXCore/Core/CPUBackend.h>
|
||||
|
@ -6,7 +6,7 @@ $end_info$
|
||||
|
||||
#include "Interface/Core/CPUID.h"
|
||||
#include "Interface/Core/JIT/x86_64/JITClass.h"
|
||||
|
||||
#include "Interface/Core/Dispatcher/X86Dispatcher.h"
|
||||
#include <FEXCore/Core/CoreState.h>
|
||||
#include <FEXCore/IR/IR.h>
|
||||
#include <FEXCore/Utils/LogManager.h>
|
||||
@ -14,7 +14,6 @@ $end_info$
|
||||
#include <array>
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
#include <xbyak/xbyak.h>
|
||||
|
||||
namespace FEXCore::CPU {
|
||||
|
||||
|
@ -6,6 +6,7 @@ $end_info$
|
||||
|
||||
#include "Interface/Context/Context.h"
|
||||
#include "Interface/Core/Dispatcher/Dispatcher.h"
|
||||
#include "Interface/Core/Dispatcher/X86Dispatcher.h"
|
||||
#include "Interface/Core/JIT/x86_64/JITClass.h"
|
||||
#include "FEXCore/Debug/InternalThreadState.h"
|
||||
|
||||
@ -16,7 +17,6 @@ $end_info$
|
||||
#include <array>
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
#include <xbyak/xbyak.h>
|
||||
|
||||
namespace FEXCore::CPU {
|
||||
#define DEF_OP(x) void X86JITCore::Op_##x(IR::IROp_Header *IROp, IR::NodeID Node)
|
||||
|
@ -5,7 +5,7 @@ $end_info$
|
||||
*/
|
||||
|
||||
#include "Interface/Core/JIT/x86_64/JITClass.h"
|
||||
|
||||
#include "Interface/Core/Dispatcher/X86Dispatcher.h"
|
||||
#include <FEXCore/Utils/LogManager.h>
|
||||
#include <FEXCore/IR/IR.h>
|
||||
|
||||
|
@ -5,14 +5,13 @@ $end_info$
|
||||
*/
|
||||
|
||||
#include "Interface/Core/JIT/x86_64/JITClass.h"
|
||||
|
||||
#include "Interface/Core/Dispatcher/X86Dispatcher.h"
|
||||
#include <FEXCore/IR/IR.h>
|
||||
#include <FEXCore/Utils/LogManager.h>
|
||||
|
||||
#include <array>
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
#include <xbyak/xbyak.h>
|
||||
|
||||
namespace FEXCore::CPU {
|
||||
|
||||
|
@ -15,11 +15,13 @@ $end_info$
|
||||
|
||||
namespace FEXCore {
|
||||
LookupCache::LookupCache(FEXCore::Context::ContextImpl *CTX)
|
||||
: ctx {CTX} {
|
||||
: BlockLinks_mbr { fextl::pmr::get_default_resource() }
|
||||
, ctx {CTX} {
|
||||
|
||||
TotalCacheSize = ctx->Config.VirtualMemSize / 4096 * 8 + CODE_SIZE + L1_SIZE;
|
||||
BlockLinks_pma = fextl::make_unique<std::pmr::polymorphic_allocator<std::byte>>(&BlockLinks_mbr);
|
||||
// Setup our PMR map.
|
||||
BlockLinks = BlockLinks_pma.new_object<BlockLinksMapType>();
|
||||
BlockLinks = BlockLinks_pma->new_object<BlockLinksMapType>();
|
||||
|
||||
// Block cache ends up looking like this
|
||||
// PageMemoryMap[VirtualMemoryRegion >> 12]
|
||||
@ -71,10 +73,8 @@ void LookupCache::ClearCache() {
|
||||
|
||||
// Clear L1 and L2 by clearing the full cache.
|
||||
madvise(reinterpret_cast<void*>(PagePointer), TotalCacheSize, MADV_DONTNEED);
|
||||
// Clear the BlockLinks allocator which frees the BlockLinks map implicitly.
|
||||
BlockLinks_mbr.release();
|
||||
// Allocate a new pointer from the BlockLinks pma again.
|
||||
BlockLinks = BlockLinks_pma.new_object<BlockLinksMapType>();
|
||||
BlockLinks = BlockLinks_pma->new_object<BlockLinksMapType>();
|
||||
// All code is gone, clear the block list
|
||||
BlockList.clear();
|
||||
}
|
||||
|
@ -2,21 +2,21 @@
|
||||
#include "Interface/Context/Context.h"
|
||||
#include <FEXCore/Utils/LogManager.h>
|
||||
#include <FEXCore/fextl/map.h>
|
||||
#include <FEXCore/fextl/memory_resource.h>
|
||||
#include <FEXCore/fextl/robin_map.h>
|
||||
#include <FEXCore/fextl/vector.h>
|
||||
#include <FEXCore/fextl/memory_resource.h>
|
||||
|
||||
#include <cstdint>
|
||||
#include <functional>
|
||||
#include <memory_resource>
|
||||
#include <stddef.h>
|
||||
#include <utility>
|
||||
#include <mutex>
|
||||
#include <tsl/robin_map.h>
|
||||
|
||||
namespace FEXCore {
|
||||
|
||||
class LookupCache {
|
||||
public:
|
||||
|
||||
struct LookupCacheEntry {
|
||||
uintptr_t HostCode;
|
||||
uintptr_t GuestCode;
|
||||
@ -245,10 +245,10 @@ private:
|
||||
// This makes `BlockLinks` look like a raw pointer that could memory leak, but since it is backed by the MBR, it won't.
|
||||
std::pmr::monotonic_buffer_resource BlockLinks_mbr;
|
||||
using BlockLinksMapType = std::pmr::map<BlockLinkTag, std::function<void()>>;
|
||||
std::pmr::polymorphic_allocator<std::byte> BlockLinks_pma {&BlockLinks_mbr};
|
||||
fextl::unique_ptr<std::pmr::polymorphic_allocator<std::byte>> BlockLinks_pma;
|
||||
BlockLinksMapType *BlockLinks;
|
||||
|
||||
tsl::robin_map<uint64_t, uint64_t> BlockList;
|
||||
fextl::robin_map<uint64_t, uint64_t> BlockList;
|
||||
|
||||
size_t TotalCacheSize;
|
||||
|
||||
|
@ -8,12 +8,12 @@
|
||||
#include <FEXCore/Utils/Threads.h>
|
||||
#include <FEXCore/fextl/map.h>
|
||||
#include <FEXCore/fextl/queue.h>
|
||||
#include <FEXCore/fextl/robin_map.h>
|
||||
#include <FEXCore/fextl/string.h>
|
||||
#include <FEXCore/fextl/vector.h>
|
||||
|
||||
#include <memory>
|
||||
#include <shared_mutex>
|
||||
#include <tsl/robin_map.h>
|
||||
|
||||
namespace FEXCore::CodeSerialize {
|
||||
// XXX: Does this need to be signal safe?
|
||||
@ -111,7 +111,7 @@ namespace FEXCore::CodeSerialize {
|
||||
|
||||
// This per section map takes the most time to load and needs to be quick
|
||||
// This is the map of all code segments for this entry
|
||||
tsl::robin_map<uint64_t, CodeObjectFileSection*> SectionLookupMap{};
|
||||
fextl::robin_map<uint64_t, CodeObjectFileSection*> SectionLookupMap{};
|
||||
/** @} */
|
||||
|
||||
// Default initialization
|
||||
|
@ -358,8 +358,8 @@ namespace FEXCore {
|
||||
}
|
||||
};
|
||||
|
||||
ThunkHandler* ThunkHandler::Create() {
|
||||
return new ThunkHandler_impl();
|
||||
fextl::unique_ptr<ThunkHandler> ThunkHandler::Create() {
|
||||
return fextl::make_unique<ThunkHandler_impl>();
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -7,6 +7,7 @@ $end_info$
|
||||
#pragma once
|
||||
|
||||
#include <FEXCore/IR/IR.h>
|
||||
#include <FEXCore/fextl/memory.h>
|
||||
#include <FEXCore/fextl/vector.h>
|
||||
|
||||
namespace FEXCore::Context {
|
||||
@ -26,12 +27,12 @@ namespace FEXCore {
|
||||
|
||||
class ThunkHandler {
|
||||
public:
|
||||
virtual ThunkedFunction* LookupThunk(const IR::SHA256Sum &sha256) = 0;
|
||||
virtual void RegisterTLSState(FEXCore::Core::InternalThreadState *Thread) = 0;
|
||||
virtual ~ThunkHandler() { }
|
||||
virtual ThunkedFunction* LookupThunk(const IR::SHA256Sum &sha256) = 0;
|
||||
virtual void RegisterTLSState(FEXCore::Core::InternalThreadState *Thread) = 0;
|
||||
virtual ~ThunkHandler() { }
|
||||
|
||||
static ThunkHandler* Create();
|
||||
static fextl::unique_ptr<ThunkHandler> Create();
|
||||
|
||||
virtual void AppendThunkDefinitions(fextl::vector<FEXCore::IR::ThunkDefinition> const& Definitions) = 0;
|
||||
virtual void AppendThunkDefinitions(fextl::vector<FEXCore::IR::ThunkDefinition> const& Definitions) = 0;
|
||||
};
|
||||
};
|
||||
|
19
External/FEXCore/Source/Interface/IR/AOTIR.cpp
vendored
19
External/FEXCore/Source/Interface/IR/AOTIR.cpp
vendored
@ -1,3 +1,4 @@
|
||||
#include "FEXHeaderUtils/Filesystem.h"
|
||||
#include "Interface/Context/Context.h"
|
||||
#include "Interface/IR/AOTIR.h"
|
||||
|
||||
@ -5,6 +6,7 @@
|
||||
#include <FEXCore/IR/RegisterAllocationData.h>
|
||||
#include <FEXCore/Utils/Allocator.h>
|
||||
#include <FEXCore/HLE/SyscallHandler.h>
|
||||
#include <FEXCore/fextl/fmt.h>
|
||||
#include <FEXCore/fextl/string.h>
|
||||
|
||||
#include <Interface/Core/LookupCache.h>
|
||||
@ -371,19 +373,18 @@ namespace FEXCore::IR {
|
||||
}
|
||||
|
||||
AOTIRCacheEntry *AOTIRCaptureCache::LoadAOTIRCacheEntry(const fextl::string &filename) {
|
||||
fextl::string base_filename = fextl::string_from_path(std::filesystem::path(filename).filename());
|
||||
fextl::string base_filename = FHU::Filesystem::GetFilename(filename);
|
||||
|
||||
if (!base_filename.empty()) {
|
||||
auto filename_hash = XXH3_64bits(filename.c_str(), filename.size());
|
||||
|
||||
auto fileid = base_filename + "-";
|
||||
fileid += std::to_string(filename_hash) + "-";
|
||||
|
||||
// append optimization flags to the fileid
|
||||
fileid += (CTX->Config.SMCChecks == FEXCore::Config::CONFIG_SMC_FULL) ? "S" : "s";
|
||||
fileid += CTX->Config.TSOEnabled ? "T" : "t";
|
||||
fileid += CTX->Config.ABILocalFlags ? "L" : "l";
|
||||
fileid += CTX->Config.ABINoPF ? "p" : "P";
|
||||
auto fileid = fextl::fmt::format("{}-{}-{}{}{}{}",
|
||||
base_filename,
|
||||
filename_hash,
|
||||
(CTX->Config.SMCChecks == FEXCore::Config::CONFIG_SMC_FULL) ? 'S' : 's',
|
||||
CTX->Config.TSOEnabled ? 'T' : 't',
|
||||
CTX->Config.ABILocalFlags ? 'L' : 'l',
|
||||
CTX->Config.ABINoPF ? 'p' : 'P');
|
||||
|
||||
std::unique_lock lk(AOTIRCacheLock);
|
||||
|
||||
|
@ -8,12 +8,12 @@ $end_info$
|
||||
|
||||
#include <FEXCore/Config/Config.h>
|
||||
#include <FEXCore/Utils/ThreadPoolAllocator.h>
|
||||
#include <FEXCore/fextl/memory.h>
|
||||
#include <FEXCore/fextl/string.h>
|
||||
#include <FEXCore/fextl/unordered_map.h>
|
||||
#include <FEXCore/fextl/vector.h>
|
||||
|
||||
#include <functional>
|
||||
#include <memory>
|
||||
#include <utility>
|
||||
|
||||
namespace FEXCore::Context {
|
||||
@ -48,7 +48,7 @@ class PassManager final {
|
||||
public:
|
||||
void AddDefaultPasses(FEXCore::Context::ContextImpl *ctx, bool InlineConstants, bool StaticRegisterAllocation);
|
||||
void AddDefaultValidationPasses();
|
||||
Pass* InsertPass(std::unique_ptr<Pass> Pass, fextl::string Name = "") {
|
||||
Pass* InsertPass(fextl::unique_ptr<Pass> Pass, fextl::string Name = "") {
|
||||
Pass->RegisterPassManager(this);
|
||||
auto PassPtr = Passes.emplace_back(std::move(Pass)).get();
|
||||
|
||||
@ -88,12 +88,12 @@ protected:
|
||||
FEXCore::HLE::SyscallHandler *SyscallHandler;
|
||||
|
||||
private:
|
||||
fextl::vector<std::unique_ptr<Pass>> Passes;
|
||||
fextl::vector<fextl::unique_ptr<Pass>> Passes;
|
||||
fextl::unordered_map<fextl::string, Pass*> NameToPassMaping;
|
||||
|
||||
#if defined(ASSERTIONS_ENABLED) && ASSERTIONS_ENABLED
|
||||
fextl::vector<std::unique_ptr<Pass>> ValidationPasses;
|
||||
void InsertValidationPass(std::unique_ptr<Pass> Pass, fextl::string Name = "") {
|
||||
fextl::vector<fextl::unique_ptr<Pass>> ValidationPasses;
|
||||
void InsertValidationPass(fextl::unique_ptr<Pass> Pass, fextl::string Name = "") {
|
||||
Pass->RegisterPassManager(this);
|
||||
auto PassPtr = ValidationPasses.emplace_back(std::move(Pass)).get();
|
||||
|
||||
|
28
External/FEXCore/Source/Interface/IR/Passes.h
vendored
28
External/FEXCore/Source/Interface/IR/Passes.h
vendored
@ -1,6 +1,6 @@
|
||||
#pragma once
|
||||
|
||||
#include <memory>
|
||||
#include <FEXCore/fextl/memory.h>
|
||||
|
||||
namespace FEXCore::Utils {
|
||||
class IntrusivePooledAllocator;
|
||||
@ -11,23 +11,23 @@ class Pass;
|
||||
class RegisterAllocationPass;
|
||||
class RegisterAllocationData;
|
||||
|
||||
std::unique_ptr<FEXCore::IR::Pass> CreateConstProp(bool InlineConstants, bool SupportsTSOImm9);
|
||||
std::unique_ptr<FEXCore::IR::Pass> CreateContextLoadStoreElimination(bool SupportsAVX);
|
||||
std::unique_ptr<FEXCore::IR::Pass> CreateSyscallOptimization();
|
||||
std::unique_ptr<FEXCore::IR::Pass> CreateDeadFlagCalculationEliminination();
|
||||
std::unique_ptr<FEXCore::IR::Pass> CreateDeadStoreElimination(bool SupportsAVX);
|
||||
std::unique_ptr<FEXCore::IR::Pass> CreatePassDeadCodeElimination();
|
||||
std::unique_ptr<FEXCore::IR::Pass> CreateIRCompaction(FEXCore::Utils::IntrusivePooledAllocator &Allocator);
|
||||
std::unique_ptr<FEXCore::IR::RegisterAllocationPass> CreateRegisterAllocationPass(FEXCore::IR::Pass* CompactionPass,
|
||||
fextl::unique_ptr<FEXCore::IR::Pass> CreateConstProp(bool InlineConstants, bool SupportsTSOImm9);
|
||||
fextl::unique_ptr<FEXCore::IR::Pass> CreateContextLoadStoreElimination(bool SupportsAVX);
|
||||
fextl::unique_ptr<FEXCore::IR::Pass> CreateSyscallOptimization();
|
||||
fextl::unique_ptr<FEXCore::IR::Pass> CreateDeadFlagCalculationEliminination();
|
||||
fextl::unique_ptr<FEXCore::IR::Pass> CreateDeadStoreElimination(bool SupportsAVX);
|
||||
fextl::unique_ptr<FEXCore::IR::Pass> CreatePassDeadCodeElimination();
|
||||
fextl::unique_ptr<FEXCore::IR::Pass> CreateIRCompaction(FEXCore::Utils::IntrusivePooledAllocator &Allocator);
|
||||
fextl::unique_ptr<FEXCore::IR::RegisterAllocationPass> CreateRegisterAllocationPass(FEXCore::IR::Pass* CompactionPass,
|
||||
bool OptimizeSRA,
|
||||
bool SupportsAVX);
|
||||
std::unique_ptr<FEXCore::IR::Pass> CreateLongDivideEliminationPass();
|
||||
fextl::unique_ptr<FEXCore::IR::Pass> CreateLongDivideEliminationPass();
|
||||
|
||||
namespace Validation {
|
||||
std::unique_ptr<FEXCore::IR::Pass> CreateIRValidation();
|
||||
std::unique_ptr<FEXCore::IR::Pass> CreateRAValidation();
|
||||
std::unique_ptr<FEXCore::IR::Pass> CreatePhiValidation();
|
||||
std::unique_ptr<FEXCore::IR::Pass> CreateValueDominanceValidation();
|
||||
fextl::unique_ptr<FEXCore::IR::Pass> CreateIRValidation();
|
||||
fextl::unique_ptr<FEXCore::IR::Pass> CreateRAValidation();
|
||||
fextl::unique_ptr<FEXCore::IR::Pass> CreatePhiValidation();
|
||||
fextl::unique_ptr<FEXCore::IR::Pass> CreateValueDominanceValidation();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -22,6 +22,7 @@ $end_info$
|
||||
#include <FEXCore/Utils/LogManager.h>
|
||||
#include <FEXCore/Utils/Profiler.h>
|
||||
#include <FEXCore/fextl/map.h>
|
||||
#include <FEXCore/fextl/robin_map.h>
|
||||
#include <FEXCore/fextl/unordered_map.h>
|
||||
|
||||
#include <bit>
|
||||
@ -29,7 +30,6 @@ $end_info$
|
||||
#include <memory>
|
||||
#include <string.h>
|
||||
#include <tuple>
|
||||
#include <tsl/robin_map.h>
|
||||
#include <utility>
|
||||
|
||||
namespace FEXCore::IR {
|
||||
@ -201,7 +201,7 @@ private:
|
||||
fextl::map<OrderedNode*, uint64_t> AddressgenConsts;
|
||||
|
||||
// Pool inline constant generation. These are typically very small and pool efficiently.
|
||||
tsl::robin_map<uint64_t, OrderedNode*> InlineConstantGen;
|
||||
fextl::robin_map<uint64_t, OrderedNode*> InlineConstantGen;
|
||||
OrderedNode *CreateInlineConstant(IREmitter *IREmit, uint64_t Constant) {
|
||||
const auto it = InlineConstantGen.find(Constant);
|
||||
if (it != InlineConstantGen.end()) {
|
||||
@ -1073,8 +1073,8 @@ bool ConstProp::Run(IREmitter *IREmit) {
|
||||
return Changed;
|
||||
}
|
||||
|
||||
std::unique_ptr<FEXCore::IR::Pass> CreateConstProp(bool InlineConstants, bool SupportsTSOImm9) {
|
||||
return std::make_unique<ConstProp>(InlineConstants, SupportsTSOImm9);
|
||||
fextl::unique_ptr<FEXCore::IR::Pass> CreateConstProp(bool InlineConstants, bool SupportsTSOImm9) {
|
||||
return fextl::make_unique<ConstProp>(InlineConstants, SupportsTSOImm9);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -80,8 +80,8 @@ void DeadCodeElimination::markUsed(OrderedNodeWrapper *CodeOp, IROp_Header *IROp
|
||||
|
||||
}
|
||||
|
||||
std::unique_ptr<FEXCore::IR::Pass> CreatePassDeadCodeElimination() {
|
||||
return std::make_unique<DeadCodeElimination>();
|
||||
fextl::unique_ptr<FEXCore::IR::Pass> CreatePassDeadCodeElimination() {
|
||||
return fextl::make_unique<DeadCodeElimination>();
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -410,7 +410,7 @@ public:
|
||||
}
|
||||
bool Run(FEXCore::IR::IREmitter *IREmit) override;
|
||||
private:
|
||||
std::unique_ptr<FEXCore::IR::Pass> DCE;
|
||||
fextl::unique_ptr<FEXCore::IR::Pass> DCE;
|
||||
|
||||
ContextInfo ClassifiedStruct;
|
||||
fextl::unordered_map<FEXCore::IR::NodeID, BlockInfo> OffsetToBlockMap;
|
||||
@ -784,8 +784,8 @@ bool RCLSE::Run(FEXCore::IR::IREmitter *IREmit) {
|
||||
|
||||
namespace FEXCore::IR {
|
||||
|
||||
std::unique_ptr<FEXCore::IR::Pass> CreateContextLoadStoreElimination(bool SupportsAVX) {
|
||||
return std::make_unique<RCLSE>(SupportsAVX);
|
||||
fextl::unique_ptr<FEXCore::IR::Pass> CreateContextLoadStoreElimination(bool SupportsAVX) {
|
||||
return fextl::make_unique<RCLSE>(SupportsAVX);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -358,8 +358,8 @@ bool DeadStoreElimination::Run(IREmitter *IREmit) {
|
||||
return Changed;
|
||||
}
|
||||
|
||||
std::unique_ptr<FEXCore::IR::Pass> CreateDeadStoreElimination(bool SupportsAVX) {
|
||||
return std::make_unique<DeadStoreElimination>(SupportsAVX);
|
||||
fextl::unique_ptr<FEXCore::IR::Pass> CreateDeadStoreElimination(bool SupportsAVX) {
|
||||
return fextl::make_unique<DeadStoreElimination>(SupportsAVX);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -220,8 +220,8 @@ bool IRCompaction::Run(IREmitter *IREmit) {
|
||||
return true;
|
||||
}
|
||||
|
||||
std::unique_ptr<FEXCore::IR::Pass> CreateIRCompaction(FEXCore::Utils::IntrusivePooledAllocator &Allocator) {
|
||||
return std::make_unique<IRCompaction>(Allocator);
|
||||
fextl::unique_ptr<FEXCore::IR::Pass> CreateIRCompaction(FEXCore::Utils::IntrusivePooledAllocator &Allocator) {
|
||||
return fextl::make_unique<IRCompaction>(Allocator);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -271,7 +271,7 @@ bool IRValidation::Run(IREmitter *IREmit) {
|
||||
return false;
|
||||
}
|
||||
|
||||
std::unique_ptr<FEXCore::IR::Pass> CreateIRValidation() {
|
||||
return std::make_unique<IRValidation>();
|
||||
fextl::unique_ptr<FEXCore::IR::Pass> CreateIRValidation() {
|
||||
return fextl::make_unique<IRValidation>();
|
||||
}
|
||||
}
|
||||
|
@ -114,7 +114,7 @@ bool LongDivideEliminationPass::Run(IREmitter *IREmit) {
|
||||
return Changed;
|
||||
}
|
||||
|
||||
std::unique_ptr<FEXCore::IR::Pass> CreateLongDivideEliminationPass() {
|
||||
return std::make_unique<LongDivideEliminationPass>();
|
||||
fextl::unique_ptr<FEXCore::IR::Pass> CreateLongDivideEliminationPass() {
|
||||
return fextl::make_unique<LongDivideEliminationPass>();
|
||||
}
|
||||
}
|
||||
|
@ -70,8 +70,8 @@ bool PhiValidation::Run(IREmitter *IREmit) {
|
||||
return false;
|
||||
}
|
||||
|
||||
std::unique_ptr<FEXCore::IR::Pass> CreatePhiValidation() {
|
||||
return std::make_unique<PhiValidation>();
|
||||
fextl::unique_ptr<FEXCore::IR::Pass> CreatePhiValidation() {
|
||||
return fextl::make_unique<PhiValidation>();
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -452,7 +452,7 @@ bool RAValidation::Run(IREmitter *IREmit) {
|
||||
return false;
|
||||
}
|
||||
|
||||
std::unique_ptr<FEXCore::IR::Pass> CreateRAValidation() {
|
||||
return std::make_unique<RAValidation>();
|
||||
fextl::unique_ptr<FEXCore::IR::Pass> CreateRAValidation() {
|
||||
return fextl::make_unique<RAValidation>();
|
||||
}
|
||||
}
|
||||
|
@ -68,8 +68,8 @@ bool DeadFlagCalculationEliminination::Run(IREmitter *IREmit) {
|
||||
return Changed;
|
||||
}
|
||||
|
||||
std::unique_ptr<FEXCore::IR::Pass> CreateDeadFlagCalculationEliminination() {
|
||||
return std::make_unique<DeadFlagCalculationEliminination>();
|
||||
fextl::unique_ptr<FEXCore::IR::Pass> CreateDeadFlagCalculationEliminination() {
|
||||
return fextl::make_unique<DeadFlagCalculationEliminination>();
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -90,7 +90,7 @@ namespace {
|
||||
IR::OrderedNode *SpilledNode;
|
||||
};
|
||||
|
||||
struct RegisterGraph {
|
||||
struct RegisterGraph : public FEXCore::Allocator::FEXAllocOperators {
|
||||
IR::RegisterAllocationData::UniquePtr AllocData;
|
||||
RegisterSet Set;
|
||||
fextl::vector<RegisterNode> Nodes{};
|
||||
@ -1559,7 +1559,7 @@ namespace {
|
||||
return Changed;
|
||||
}
|
||||
|
||||
std::unique_ptr<FEXCore::IR::RegisterAllocationPass> CreateRegisterAllocationPass(FEXCore::IR::Pass* CompactionPass, bool OptimizeSRA, bool SupportsAVX) {
|
||||
return std::make_unique<ConstrainedRAPass>(CompactionPass, OptimizeSRA, SupportsAVX);
|
||||
fextl::unique_ptr<FEXCore::IR::RegisterAllocationPass> CreateRegisterAllocationPass(FEXCore::IR::Pass* CompactionPass, bool OptimizeSRA, bool SupportsAVX) {
|
||||
return fextl::make_unique<ConstrainedRAPass>(CompactionPass, OptimizeSRA, SupportsAVX);
|
||||
}
|
||||
}
|
||||
|
@ -82,8 +82,8 @@ bool SyscallOptimization::Run(IREmitter *IREmit) {
|
||||
return Changed;
|
||||
}
|
||||
|
||||
std::unique_ptr<FEXCore::IR::Pass> CreateSyscallOptimization() {
|
||||
return std::make_unique<SyscallOptimization>();
|
||||
fextl::unique_ptr<FEXCore::IR::Pass> CreateSyscallOptimization() {
|
||||
return fextl::make_unique<SyscallOptimization>();
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -206,8 +206,8 @@ bool ValueDominanceValidation::Run(IREmitter *IREmit) {
|
||||
return false;
|
||||
}
|
||||
|
||||
std::unique_ptr<FEXCore::IR::Pass> CreateValueDominanceValidation() {
|
||||
return std::make_unique<ValueDominanceValidation>();
|
||||
fextl::unique_ptr<FEXCore::IR::Pass> CreateValueDominanceValidation() {
|
||||
return fextl::make_unique<ValueDominanceValidation>();
|
||||
}
|
||||
|
||||
}
|
||||
|
10
External/FEXCore/Source/Utils/Allocator.cpp
vendored
10
External/FEXCore/Source/Utils/Allocator.cpp
vendored
@ -2,6 +2,7 @@
|
||||
#include <FEXCore/Utils/Allocator.h>
|
||||
#include <FEXCore/Utils/CompilerDefs.h>
|
||||
#include <FEXCore/Utils/LogManager.h>
|
||||
#include <FEXCore/fextl/memory_resource.h>
|
||||
#include <FEXHeaderUtils/Syscalls.h>
|
||||
#include <FEXHeaderUtils/TypeDefines.h>
|
||||
|
||||
@ -32,6 +33,13 @@ extern "C" {
|
||||
#endif
|
||||
}
|
||||
|
||||
namespace fextl::pmr {
|
||||
static fextl::pmr::default_resource FEXDefaultResource;
|
||||
std::pmr::memory_resource* get_default_resource() {
|
||||
return &FEXDefaultResource;
|
||||
}
|
||||
}
|
||||
|
||||
namespace FEXCore::Allocator {
|
||||
MMAP_Hook mmap {::mmap};
|
||||
MUNMAP_Hook munmap {::munmap};
|
||||
@ -63,7 +71,7 @@ namespace FEXCore::Allocator {
|
||||
using GLIBC_REALLOC_Hook = void*(*)(void*, size_t, const void *caller);
|
||||
using GLIBC_FREE_Hook = void(*)(void*, const void *caller);
|
||||
|
||||
std::unique_ptr<Alloc::HostAllocator> Alloc64{};
|
||||
fextl::unique_ptr<Alloc::HostAllocator> Alloc64{};
|
||||
|
||||
void *FEX_mmap(void *addr, size_t length, int prot, int flags, int fd, off_t offset) {
|
||||
void *Result = Alloc64->Mmap(addr, length, prot, flags, fd, offset);
|
||||
|
@ -8,6 +8,7 @@
|
||||
#include <FEXHeaderUtils/ScopedSignalMask.h>
|
||||
#include <FEXHeaderUtils/Syscalls.h>
|
||||
#include <FEXHeaderUtils/TypeDefines.h>
|
||||
#include <FEXCore/fextl/memory.h>
|
||||
#include <FEXCore/fextl/vector.h>
|
||||
|
||||
#include <algorithm>
|
||||
@ -142,7 +143,9 @@ namespace Alloc::OSAllocator {
|
||||
|
||||
[[maybe_unused]] auto Res = mprotect(reinterpret_cast<void*>(ReservedRegion->Base), SizePlusManagedData, PROT_READ | PROT_WRITE);
|
||||
|
||||
LOGMAN_THROW_AA_FMT(Res == 0, "Couldn't mprotect region: {} '{}' Likely occurs when running out of memory or Maximum VMAs", errno, strerror(errno));
|
||||
if (Res == -1) {
|
||||
LOGMAN_MSG_A_FMT("Couldn't mprotect region: {} '{}' Likely occurs when running out of memory or Maximum VMAs", errno, strerror(errno));
|
||||
}
|
||||
|
||||
LiveVMARegion *LiveRange = new (reinterpret_cast<void*>(ReservedRegion->Base)) LiveVMARegion();
|
||||
|
||||
@ -572,7 +575,7 @@ OSAllocator_64Bit::~OSAllocator_64Bit() {
|
||||
}
|
||||
}
|
||||
|
||||
std::unique_ptr<Alloc::HostAllocator> Create64BitAllocator() {
|
||||
return std::make_unique<OSAllocator_64Bit>();
|
||||
fextl::unique_ptr<Alloc::HostAllocator> Create64BitAllocator() {
|
||||
return fextl::make_unique<OSAllocator_64Bit>();
|
||||
}
|
||||
}
|
||||
|
@ -1,8 +1,9 @@
|
||||
#pragma once
|
||||
#include <FEXCore/fextl/allocator.h>
|
||||
#include <FEXCore/fextl/memory.h>
|
||||
|
||||
#include <cstddef>
|
||||
#include <cstdint>
|
||||
#include <memory>
|
||||
#include <sys/types.h>
|
||||
|
||||
namespace Alloc {
|
||||
@ -35,5 +36,5 @@ namespace Alloc {
|
||||
}
|
||||
|
||||
namespace Alloc::OSAllocator {
|
||||
std::unique_ptr<Alloc::HostAllocator> Create64BitAllocator();
|
||||
fextl::unique_ptr<Alloc::HostAllocator> Create64BitAllocator();
|
||||
}
|
||||
|
157
External/FEXCore/Source/Utils/AllocatorOverride.cpp
vendored
Normal file
157
External/FEXCore/Source/Utils/AllocatorOverride.cpp
vendored
Normal file
@ -0,0 +1,157 @@
|
||||
#include <FEXCore/Utils/Allocator.h>
|
||||
#include <FEXCore/Utils/CompilerDefs.h>
|
||||
#include <FEXCore/Utils/LogManager.h>
|
||||
|
||||
#include <fmt/format.h>
|
||||
|
||||
#include <cstddef>
|
||||
#include <cstdint>
|
||||
#include <fstream>
|
||||
#include <sstream>
|
||||
#include <unistd.h>
|
||||
|
||||
extern "C" {
|
||||
// The majority of FEX internal code should avoid using the glibc allocator. To ensure glibc allocations don't accidentally slip
|
||||
// in, FEX overrides these glibc functions with faulting variants.
|
||||
//
|
||||
// A notable exception is thunks, which should still use glibc allocations and avoid using `fextl::` namespace.
|
||||
//
|
||||
// Other minor exceptions throughout FEX use the `YesIKnowImNotSupposedToUseTheGlibcAllocator` helper to temporarily disable faulting.
|
||||
#define GLIBC_ALIAS_FUNCTION(func) __attribute__((alias(#func), visibility("default")))
|
||||
extern void *__libc_calloc(size_t, size_t);
|
||||
void *calloc(size_t, size_t) GLIBC_ALIAS_FUNCTION(fault_calloc);
|
||||
|
||||
extern void __libc_free(void*);
|
||||
void free(void*) GLIBC_ALIAS_FUNCTION(fault_free);
|
||||
|
||||
extern void *__libc_malloc(size_t);
|
||||
void *malloc(size_t) GLIBC_ALIAS_FUNCTION(fault_malloc);
|
||||
|
||||
extern void *__libc_memalign(size_t, size_t);
|
||||
void *memalign(size_t, size_t) GLIBC_ALIAS_FUNCTION(fault_memalign);
|
||||
|
||||
extern void *__libc_realloc(void*, size_t);
|
||||
void *realloc(void*, size_t) GLIBC_ALIAS_FUNCTION(fault_realloc);
|
||||
|
||||
extern void *__libc_valloc(size_t);
|
||||
void *valloc(size_t) GLIBC_ALIAS_FUNCTION(fault_valloc);
|
||||
|
||||
extern int __posix_memalign(void **, size_t, size_t);
|
||||
int posix_memalign(void **, size_t, size_t) GLIBC_ALIAS_FUNCTION(fault_posix_memalign);
|
||||
|
||||
extern size_t __malloc_usable_size(void*);
|
||||
size_t malloc_usable_size(void*) GLIBC_ALIAS_FUNCTION(fault_malloc_usable_size);
|
||||
|
||||
// Reuse __libc_memalign
|
||||
void *aligned_alloc(size_t, size_t) GLIBC_ALIAS_FUNCTION(fault_aligned_alloc);
|
||||
}
|
||||
|
||||
namespace FEXCore::Allocator {
|
||||
// Enable or disable allocation faulting globally.
|
||||
static bool GlobalEvaluate{};
|
||||
|
||||
// Enable or disable allocation faulting per-thread.
|
||||
static thread_local uint64_t SkipEvalForThread{};
|
||||
|
||||
// Internal memory allocation hooks to allow non-faulting allocations through.
|
||||
CALLOC_Hook calloc_ptr = __libc_calloc;
|
||||
FREE_Hook free_ptr = __libc_free;
|
||||
MALLOC_Hook malloc_ptr = __libc_malloc;
|
||||
MEMALIGN_Hook memalign_ptr = __libc_memalign;
|
||||
REALLOC_Hook realloc_ptr = __libc_realloc;
|
||||
VALLOC_Hook valloc_ptr = __libc_valloc;
|
||||
POSIX_MEMALIGN_Hook posix_memalign_ptr = ::posix_memalign;
|
||||
MALLOC_USABLE_SIZE_Hook malloc_usable_size_ptr = ::malloc_usable_size;
|
||||
ALIGNED_ALLOC_Hook aligned_alloc_ptr = __libc_memalign;
|
||||
|
||||
// Constructor for per-thread allocation faulting check.
|
||||
YesIKnowImNotSupposedToUseTheGlibcAllocator::YesIKnowImNotSupposedToUseTheGlibcAllocator() {
|
||||
++SkipEvalForThread;
|
||||
}
|
||||
|
||||
// Destructor for per-thread allocation faulting check.
|
||||
YesIKnowImNotSupposedToUseTheGlibcAllocator::~YesIKnowImNotSupposedToUseTheGlibcAllocator() {
|
||||
--SkipEvalForThread;
|
||||
}
|
||||
|
||||
// Hard disabling of per-thread allocation fault checking.
|
||||
// No coming back from this, used on thread destruction.
|
||||
FEX_DEFAULT_VISIBILITY void YesIKnowImNotSupposedToUseTheGlibcAllocator::HardDisable() {
|
||||
// Just set it to half of its maximum value so it never wraps back around.
|
||||
SkipEvalForThread = std::numeric_limits<decltype(SkipEvalForThread)>::max() / 2;
|
||||
}
|
||||
|
||||
// Enable global fault checking.
|
||||
void SetupFaultEvaluate() {
|
||||
GlobalEvaluate = true;
|
||||
}
|
||||
|
||||
// Disable global fault checking.
|
||||
void ClearFaultEvaluate() {
|
||||
GlobalEvaluate = false;
|
||||
}
|
||||
|
||||
// Evaluate if a glibc hooked allocation should fault.
|
||||
void EvaluateReturnAddress(void* Return) {
|
||||
if (!GlobalEvaluate) {
|
||||
// Fault evaluation disabled globally.
|
||||
return;
|
||||
}
|
||||
|
||||
if (SkipEvalForThread) {
|
||||
// Fault evaluation currently disabled for this thread.
|
||||
return;
|
||||
}
|
||||
|
||||
// We don't know where we are when allocating. Make sure to be safe and generate the string on the stack.
|
||||
// Print an error message to let a developer know that an allocation faulted.
|
||||
char Tmp[512];
|
||||
auto Res = fmt::format_to_n(Tmp, 512, "Allocation from 0x{:x}\n", reinterpret_cast<uint64_t>(Return));
|
||||
Tmp[Res.size] = 0;
|
||||
write(STDERR_FILENO, Tmp, Res.size);
|
||||
|
||||
// Trap the execution to stop FEX in its tracks.
|
||||
FEX_TRAP_EXECUTION;
|
||||
}
|
||||
}
|
||||
|
||||
extern "C" {
|
||||
// These are the glibc allocator override symbols.
|
||||
// These will override the glibc allocators and then check if the allocation should fault.
|
||||
void *fault_calloc(size_t n, size_t size) {
|
||||
FEXCore::Allocator::EvaluateReturnAddress(__builtin_extract_return_addr (__builtin_return_address (0)));
|
||||
return FEXCore::Allocator::calloc_ptr(n, size);
|
||||
}
|
||||
void fault_free(void* ptr) {
|
||||
FEXCore::Allocator::EvaluateReturnAddress(__builtin_extract_return_addr (__builtin_return_address (0)));
|
||||
FEXCore::Allocator::free_ptr(ptr);
|
||||
}
|
||||
void *fault_malloc(size_t size) {
|
||||
FEXCore::Allocator::EvaluateReturnAddress(__builtin_extract_return_addr (__builtin_return_address (0)));
|
||||
return FEXCore::Allocator::malloc_ptr(size);
|
||||
}
|
||||
void *fault_memalign(size_t align, size_t s) {
|
||||
FEXCore::Allocator::EvaluateReturnAddress(__builtin_extract_return_addr (__builtin_return_address (0)));
|
||||
return FEXCore::Allocator::memalign_ptr(align, s);
|
||||
}
|
||||
void *fault_realloc(void* ptr, size_t size) {
|
||||
FEXCore::Allocator::EvaluateReturnAddress(__builtin_extract_return_addr (__builtin_return_address (0)));
|
||||
return FEXCore::Allocator::realloc_ptr(ptr, size);
|
||||
}
|
||||
void *fault_valloc(size_t size) {
|
||||
FEXCore::Allocator::EvaluateReturnAddress(__builtin_extract_return_addr (__builtin_return_address (0)));
|
||||
return FEXCore::Allocator::valloc_ptr(size);
|
||||
}
|
||||
int fault_posix_memalign(void ** r, size_t a, size_t s) {
|
||||
FEXCore::Allocator::EvaluateReturnAddress(__builtin_extract_return_addr (__builtin_return_address (0)));
|
||||
return FEXCore::Allocator::posix_memalign_ptr(r, a, s);
|
||||
}
|
||||
size_t fault_malloc_usable_size(void *ptr) {
|
||||
FEXCore::Allocator::EvaluateReturnAddress(__builtin_extract_return_addr (__builtin_return_address (0)));
|
||||
return FEXCore::Allocator::malloc_usable_size_ptr(ptr);
|
||||
}
|
||||
void *fault_aligned_alloc(size_t a, size_t s) {
|
||||
FEXCore::Allocator::EvaluateReturnAddress(__builtin_extract_return_addr (__builtin_return_address (0)));
|
||||
return FEXCore::Allocator::aligned_alloc_ptr(a, s);
|
||||
}
|
||||
}
|
6
External/FEXCore/Source/Utils/LogManager.cpp
vendored
6
External/FEXCore/Source/Utils/LogManager.cpp
vendored
@ -6,10 +6,10 @@ $end_info$
|
||||
|
||||
#include <FEXCore/Utils/CompilerDefs.h>
|
||||
#include <FEXCore/Utils/LogManager.h>
|
||||
#include <FEXCore/fextl/fmt.h>
|
||||
#include <FEXCore/fextl/vector.h>
|
||||
|
||||
#include <alloca.h>
|
||||
#include <fmt/format.h>
|
||||
#include <cstdarg>
|
||||
#include <cstdio>
|
||||
|
||||
@ -21,7 +21,7 @@ void InstallHandler(ThrowHandler Handler) { Handlers.emplace_back(Handler); }
|
||||
void UnInstallHandlers() { Handlers.clear(); }
|
||||
|
||||
void MFmt(const char *fmt, const fmt::format_args& args) {
|
||||
auto msg = fmt::vformat(fmt, args);
|
||||
auto msg = fextl::fmt::vformat(fmt, args);
|
||||
|
||||
for (auto& Handler : Handlers) {
|
||||
Handler(msg.c_str());
|
||||
@ -69,7 +69,7 @@ void D(const char *fmt, ...) {
|
||||
}
|
||||
|
||||
void MFmtImpl(DebugLevels level, const char* fmt, const fmt::format_args& args) {
|
||||
const auto msg = fmt::vformat(fmt, args);
|
||||
const auto msg = fextl::fmt::vformat(fmt, args);
|
||||
|
||||
for (auto& Handler : Handlers) {
|
||||
Handler(level, msg.c_str());
|
||||
|
26
External/FEXCore/Source/Utils/Telemetry.cpp
vendored
26
External/FEXCore/Source/Utils/Telemetry.cpp
vendored
@ -1,7 +1,9 @@
|
||||
#include <FEXCore/Config/Config.h>
|
||||
#include <FEXCore/Utils/LogManager.h>
|
||||
#include <FEXCore/Utils/Telemetry.h>
|
||||
#include <FEXCore/fextl/fmt.h>
|
||||
#include <FEXCore/fextl/string.h>
|
||||
#include <FEXHeaderUtils/Filesystem.h>
|
||||
|
||||
#include <array>
|
||||
#include <filesystem>
|
||||
@ -28,9 +30,8 @@ namespace FEXCore::Telemetry {
|
||||
DataDirectory += "Telemetry/";
|
||||
|
||||
// Ensure the folder structure is created for our configuration
|
||||
std::error_code ec{};
|
||||
if (!std::filesystem::exists(DataDirectory, ec) &&
|
||||
!std::filesystem::create_directories(DataDirectory, ec)) {
|
||||
if (!FHU::Filesystem::Exists(DataDirectory) &&
|
||||
!FHU::Filesystem::CreateDirectories(DataDirectory)) {
|
||||
LogMan::Msg::IFmt("Couldn't create telemetry Folder");
|
||||
}
|
||||
}
|
||||
@ -39,23 +40,24 @@ namespace FEXCore::Telemetry {
|
||||
auto DataDirectory = Config::GetDataDirectory();
|
||||
DataDirectory += "Telemetry/" + ApplicationName + ".telem";
|
||||
|
||||
std::error_code ec{};
|
||||
if (std::filesystem::exists(DataDirectory, ec)) {
|
||||
if (FHU::Filesystem::Exists(DataDirectory)) {
|
||||
// If the file exists, retain a single backup
|
||||
auto Backup = DataDirectory + ".1";
|
||||
std::filesystem::copy_file(DataDirectory, Backup, std::filesystem::copy_options::overwrite_existing, ec);
|
||||
FHU::Filesystem::CopyFile(DataDirectory, Backup, FHU::Filesystem::CopyOptions::OVERWRITE_EXISTING);
|
||||
}
|
||||
|
||||
std::fstream fs(fextl::string_from_string(DataDirectory), std::ios_base::out | std::ios_base::trunc);
|
||||
if (fs.is_open()) {
|
||||
constexpr int USER_PERMS = S_IRWXU | S_IRWXG | S_IRWXO;
|
||||
int fd = open(DataDirectory.c_str(), O_CREAT | O_WRONLY | O_TRUNC | O_CLOEXEC, USER_PERMS);
|
||||
|
||||
if (fd != -1) {
|
||||
for (size_t i = 0; i < TelemetryType::TYPE_LAST; ++i) {
|
||||
auto &Name = TelemetryNames.at(i);
|
||||
auto &Data = TelemetryValues.at(i);
|
||||
fs << Name << ": " << *Data << std::endl;
|
||||
auto Output = fextl::fmt::format("{}: {}\n", Name, *Data);
|
||||
write(fd, Output.c_str(), Output.size());
|
||||
}
|
||||
|
||||
fs.flush();
|
||||
fs.close();
|
||||
fsync(fd);
|
||||
close(fd);
|
||||
}
|
||||
}
|
||||
|
||||
|
17
External/FEXCore/Source/Utils/Threads.cpp
vendored
17
External/FEXCore/Source/Utils/Threads.cpp
vendored
@ -1,12 +1,12 @@
|
||||
#include <FEXCore/Utils/Allocator.h>
|
||||
#include <FEXCore/Utils/LogManager.h>
|
||||
#include <FEXCore/Utils/Threads.h>
|
||||
#include <FEXCore/fextl/memory.h>
|
||||
#include <FEXCore/fextl/deque.h>
|
||||
|
||||
#include <alloca.h>
|
||||
#include <cstring>
|
||||
#include <functional>
|
||||
#include <memory>
|
||||
#include <mutex>
|
||||
#include <pthread.h>
|
||||
#include <stdint.h>
|
||||
@ -97,9 +97,14 @@ namespace FEXCore::Threads {
|
||||
, UserArg {Arg} {
|
||||
pthread_attr_t Attr{};
|
||||
Stack = AllocateStackObject(STACK_SIZE);
|
||||
// pthreads allocates its dtv region behind our back and there is nothing we can do about it.
|
||||
FEXCore::Allocator::YesIKnowImNotSupposedToUseTheGlibcAllocator glibc;
|
||||
AddStackToLivePool(Stack, STACK_SIZE);
|
||||
pthread_attr_init(&Attr);
|
||||
pthread_attr_setstack(&Attr, Stack, STACK_SIZE);
|
||||
// TODO: Thread creation should be using this instead.
|
||||
// Causes Steam to crash early though.
|
||||
// pthread_create(&Thread, &Attr, InitializeThread, this);
|
||||
pthread_create(&Thread, &Attr, Func, Arg);
|
||||
|
||||
pthread_attr_destroy(&Attr);
|
||||
@ -155,13 +160,17 @@ namespace FEXCore::Threads {
|
||||
|
||||
// Put the stack back in to the stack pool
|
||||
Thread->FreeStack();
|
||||
|
||||
// TLS/DTV teardown is something FEX can't control. Disable glibc checking when we leave a pthread.
|
||||
FEXCore::Allocator::YesIKnowImNotSupposedToUseTheGlibcAllocator::HardDisable();
|
||||
|
||||
return Result;
|
||||
}
|
||||
|
||||
std::unique_ptr<FEXCore::Threads::Thread> CreateThread_PThread(
|
||||
fextl::unique_ptr<FEXCore::Threads::Thread> CreateThread_PThread(
|
||||
ThreadFunc Func,
|
||||
void* Arg) {
|
||||
return std::make_unique<PThread>(Func, Arg);
|
||||
return fextl::make_unique<PThread>(Func, Arg);
|
||||
}
|
||||
|
||||
void CleanupAfterFork_PThread() {
|
||||
@ -199,7 +208,7 @@ namespace FEXCore::Threads {
|
||||
.CleanupAfterFork = CleanupAfterFork_PThread,
|
||||
};
|
||||
|
||||
std::unique_ptr<FEXCore::Threads::Thread> FEXCore::Threads::Thread::Create(
|
||||
fextl::unique_ptr<FEXCore::Threads::Thread> FEXCore::Threads::Thread::Create(
|
||||
ThreadFunc Func,
|
||||
void* Arg) {
|
||||
return Ptrs.CreateThread(Func, Arg);
|
||||
|
12
External/FEXCore/include/FEXCore/Config/Config.h
vendored
12
External/FEXCore/include/FEXCore/Config/Config.h
vendored
@ -3,11 +3,11 @@
|
||||
#include <FEXCore/Core/Context.h>
|
||||
#include <FEXCore/Utils/CompilerDefs.h>
|
||||
#include <FEXCore/Utils/LogManager.h>
|
||||
#include <FEXCore/fextl/memory.h>
|
||||
#include <FEXCore/fextl/list.h>
|
||||
#include <FEXCore/fextl/string.h>
|
||||
#include <FEXCore/fextl/unordered_map.h>
|
||||
|
||||
#include <memory>
|
||||
#include <optional>
|
||||
#include <stdint.h>
|
||||
|
||||
@ -170,7 +170,7 @@ namespace Type {
|
||||
FEX_DEFAULT_VISIBILITY fextl::string FindContainer();
|
||||
FEX_DEFAULT_VISIBILITY fextl::string FindContainerPrefix();
|
||||
|
||||
FEX_DEFAULT_VISIBILITY void AddLayer(std::unique_ptr<FEXCore::Config::Layer> _Layer);
|
||||
FEX_DEFAULT_VISIBILITY void AddLayer(fextl::unique_ptr<FEXCore::Config::Layer> _Layer);
|
||||
|
||||
FEX_DEFAULT_VISIBILITY bool Exists(ConfigOption Option);
|
||||
FEX_DEFAULT_VISIBILITY std::optional<LayerValue*> All(ConfigOption Option);
|
||||
@ -255,7 +255,7 @@ namespace Type {
|
||||
*
|
||||
* @return unique_ptr for that layer
|
||||
*/
|
||||
FEX_DEFAULT_VISIBILITY std::unique_ptr<FEXCore::Config::Layer> CreateGlobalMainLayer();
|
||||
FEX_DEFAULT_VISIBILITY fextl::unique_ptr<FEXCore::Config::Layer> CreateGlobalMainLayer();
|
||||
|
||||
/**
|
||||
* @brief Loads the main application config
|
||||
@ -265,7 +265,7 @@ namespace Type {
|
||||
*
|
||||
* @return unique_ptr for that layer
|
||||
*/
|
||||
FEX_DEFAULT_VISIBILITY std::unique_ptr<FEXCore::Config::Layer> CreateMainLayer(fextl::string const *File = nullptr);
|
||||
FEX_DEFAULT_VISIBILITY fextl::unique_ptr<FEXCore::Config::Layer> CreateMainLayer(fextl::string const *File = nullptr);
|
||||
|
||||
/**
|
||||
* @brief Create an application configuration loader
|
||||
@ -275,7 +275,7 @@ namespace Type {
|
||||
*
|
||||
* @return unique_ptr for that layer
|
||||
*/
|
||||
FEX_DEFAULT_VISIBILITY std::unique_ptr<FEXCore::Config::Layer> CreateAppLayer(const fextl::string& Filename, FEXCore::Config::LayerType Type);
|
||||
FEX_DEFAULT_VISIBILITY fextl::unique_ptr<FEXCore::Config::Layer> CreateAppLayer(const fextl::string& Filename, FEXCore::Config::LayerType Type);
|
||||
|
||||
/**
|
||||
* @brief iCreate an environment configuration loader
|
||||
@ -284,6 +284,6 @@ namespace Type {
|
||||
*
|
||||
* @return unique_ptr for that layer
|
||||
*/
|
||||
FEX_DEFAULT_VISIBILITY std::unique_ptr<FEXCore::Config::Layer> CreateEnvironmentLayer(char *const _envp[]);
|
||||
FEX_DEFAULT_VISIBILITY fextl::unique_ptr<FEXCore::Config::Layer> CreateEnvironmentLayer(char *const _envp[]);
|
||||
|
||||
}
|
||||
|
@ -17,9 +17,6 @@ class IREmitter;
|
||||
*/
|
||||
class CodeLoader {
|
||||
public:
|
||||
using MapperFn = std::function<void *(void *addr, size_t length, int prot, int flags, int fd, off_t offset)>;
|
||||
using UnmapperFn = std::function<int(void *addr, size_t length)>;
|
||||
|
||||
virtual ~CodeLoader() = default;
|
||||
|
||||
/**
|
||||
@ -37,11 +34,6 @@ public:
|
||||
*/
|
||||
virtual uint64_t DefaultRIP() const = 0;
|
||||
|
||||
/**
|
||||
* @brief Maps and copies the executable, also sets up stack
|
||||
*/
|
||||
virtual bool MapMemory(const MapperFn& Mapper, const UnmapperFn& Unmapper) { return false; }
|
||||
|
||||
virtual fextl::vector<fextl::string> const *GetApplicationArguments() { return nullptr; }
|
||||
virtual void GetExecveArguments(fextl::vector<char const*> *Args) {}
|
||||
|
||||
|
@ -6,13 +6,13 @@
|
||||
#include <FEXCore/Core/CPUID.h>
|
||||
#include <FEXCore/IR/IR.h>
|
||||
#include <FEXCore/Utils/CompilerDefs.h>
|
||||
#include <FEXCore/fextl/memory.h>
|
||||
#include <FEXCore/fextl/set.h>
|
||||
#include <FEXCore/fextl/string.h>
|
||||
#include <FEXCore/fextl/vector.h>
|
||||
|
||||
#include <istream>
|
||||
#include <ostream>
|
||||
#include <memory>
|
||||
#include <mutex>
|
||||
#include <shared_mutex>
|
||||
|
||||
@ -75,7 +75,7 @@ namespace FEXCore::Context {
|
||||
void *VDSO_kernel_rt_sigreturn;
|
||||
};
|
||||
|
||||
using CustomCPUFactoryType = std::function<std::unique_ptr<FEXCore::CPU::CPUBackend> (FEXCore::Context::Context*, FEXCore::Core::InternalThreadState *Thread)>;
|
||||
using CustomCPUFactoryType = std::function<fextl::unique_ptr<FEXCore::CPU::CPUBackend> (FEXCore::Context::Context*, FEXCore::Core::InternalThreadState *Thread)>;
|
||||
|
||||
using ExitHandler = std::function<void(uint64_t ThreadId, FEXCore::Context::ExitReason)>;
|
||||
|
||||
@ -291,5 +291,4 @@ namespace FEXCore::Context {
|
||||
* @brief This initializes internal FEXCore state that is shared between contexts and requires overhead to setup
|
||||
*/
|
||||
FEX_DEFAULT_VISIBILITY void InitializeStaticTables(OperatingMode Mode = MODE_64BIT);
|
||||
FEX_DEFAULT_VISIBILITY void ShutdownStaticTables();
|
||||
}
|
||||
|
@ -7,11 +7,12 @@
|
||||
#include <FEXCore/Utils/Event.h>
|
||||
#include <FEXCore/Utils/InterruptableConditionVariable.h>
|
||||
#include <FEXCore/Utils/Threads.h>
|
||||
#include <FEXCore/fextl/memory.h>
|
||||
#include <FEXCore/fextl/robin_map.h>
|
||||
#include <FEXCore/fextl/vector.h>
|
||||
|
||||
#include <tsl/robin_map.h>
|
||||
|
||||
#include <shared_mutex>
|
||||
#include <type_traits>
|
||||
|
||||
namespace FEXCore {
|
||||
class LookupCache;
|
||||
@ -57,7 +58,7 @@ namespace FEXCore::Core {
|
||||
*
|
||||
* Needs to remain around for as long as the code could be executed at least
|
||||
*/
|
||||
struct DebugData {
|
||||
struct DebugData : public FEXCore::Allocator::FEXAllocOperators {
|
||||
uint64_t HostCodeSize; ///< The size of the code generated in the host JIT
|
||||
fextl::vector<DebugDataSubblock> Subblocks;
|
||||
fextl::vector<DebugDataGuestOpcode> GuestOpcodes;
|
||||
@ -75,12 +76,12 @@ namespace FEXCore::Core {
|
||||
struct LocalIREntry {
|
||||
uint64_t StartAddr;
|
||||
uint64_t Length;
|
||||
std::unique_ptr<FEXCore::IR::IRListView, FEXCore::IR::IRListViewDeleter> IR;
|
||||
fextl::unique_ptr<FEXCore::IR::IRListView, FEXCore::IR::IRListViewDeleter> IR;
|
||||
FEXCore::IR::RegisterAllocationData::UniquePtr RAData;
|
||||
std::unique_ptr<FEXCore::Core::DebugData> DebugData;
|
||||
fextl::unique_ptr<FEXCore::Core::DebugData> DebugData;
|
||||
};
|
||||
|
||||
struct InternalThreadState {
|
||||
struct InternalThreadState : public FEXCore::Allocator::FEXAllocOperators {
|
||||
FEXCore::Core::CpuStateFrame* const CurrentFrame = &BaseFrameState;
|
||||
|
||||
struct {
|
||||
@ -93,20 +94,20 @@ namespace FEXCore::Core {
|
||||
FEXCore::Context::Context *CTX;
|
||||
std::atomic<SignalEvent> SignalReason{SignalEvent::Nothing};
|
||||
|
||||
std::unique_ptr<FEXCore::Threads::Thread> ExecutionThread;
|
||||
fextl::unique_ptr<FEXCore::Threads::Thread> ExecutionThread;
|
||||
bool StartPaused {false};
|
||||
InterruptableConditionVariable StartRunning;
|
||||
Event ThreadWaiting;
|
||||
|
||||
std::unique_ptr<FEXCore::IR::OpDispatchBuilder> OpDispatcher;
|
||||
fextl::unique_ptr<FEXCore::IR::OpDispatchBuilder> OpDispatcher;
|
||||
|
||||
std::unique_ptr<FEXCore::CPU::CPUBackend> CPUBackend;
|
||||
std::unique_ptr<FEXCore::LookupCache> LookupCache;
|
||||
fextl::unique_ptr<FEXCore::CPU::CPUBackend> CPUBackend;
|
||||
fextl::unique_ptr<FEXCore::LookupCache> LookupCache;
|
||||
|
||||
tsl::robin_map<uint64_t, LocalIREntry> DebugStore;
|
||||
fextl::robin_map<uint64_t, LocalIREntry> DebugStore;
|
||||
|
||||
std::unique_ptr<FEXCore::Frontend::Decoder> FrontendDecoder;
|
||||
std::unique_ptr<FEXCore::IR::PassManager> PassManager;
|
||||
fextl::unique_ptr<FEXCore::Frontend::Decoder> FrontendDecoder;
|
||||
fextl::unique_ptr<FEXCore::IR::PassManager> PassManager;
|
||||
FEXCore::HLE::ThreadManagement ThreadManager;
|
||||
|
||||
RuntimeStats Stats{};
|
||||
|
@ -1,5 +1,6 @@
|
||||
#pragma once
|
||||
#include <FEXCore/fextl/fmt.h>
|
||||
#include <FEXCore/fextl/memory.h>
|
||||
#include <FEXCore/fextl/string.h>
|
||||
#include <FEXCore/fextl/vector.h>
|
||||
|
||||
@ -91,6 +92,6 @@ private:
|
||||
|
||||
class SourcecodeResolver {
|
||||
public:
|
||||
virtual std::unique_ptr<SourcecodeMap> GenerateMap(const std::string_view& GuestBinaryFile, const std::string_view& GuestBinaryFileId) = 0;
|
||||
virtual fextl::unique_ptr<SourcecodeMap> GenerateMap(const std::string_view& GuestBinaryFile, const std::string_view& GuestBinaryFileId) = 0;
|
||||
};
|
||||
}
|
||||
|
@ -120,7 +120,7 @@ class DualIntrusiveAllocatorThreadPool final : public DualIntrusiveAllocator {
|
||||
Utils::FixedSizePooledAllocation<uintptr_t, 5000, 500> PoolObject;
|
||||
};
|
||||
|
||||
class IRListView final {
|
||||
class IRListView final : public FEXCore::Allocator::FEXAllocOperators {
|
||||
enum Flags {
|
||||
FLAG_IsCopy = 1,
|
||||
FLAG_Shared = 2,
|
||||
@ -183,7 +183,7 @@ public:
|
||||
//uint64_t Flags;
|
||||
uint64_t WrittenFlags = FLAG_Shared; //on disk format always has the Shared flag
|
||||
stream.write((const char*)&WrittenFlags, sizeof(WrittenFlags));
|
||||
|
||||
|
||||
// inline data
|
||||
stream.write((const char*)GetData(), DataSize);
|
||||
stream.write((const char*)GetListData(), ListSize);
|
||||
@ -202,7 +202,7 @@ public:
|
||||
//uint64_t Flags;
|
||||
uint64_t WrittenFlags = FLAG_Shared; //on disk format always has the Shared flag
|
||||
memcpy(ptr, &WrittenFlags, sizeof(WrittenFlags)); ptr += sizeof(WrittenFlags);
|
||||
|
||||
|
||||
// inline data
|
||||
memcpy(ptr, (const void*)GetData(), DataSize); ptr += DataSize;
|
||||
memcpy(ptr, (const void*)GetListData(), ListSize); ptr += ListSize;
|
||||
|
@ -13,6 +13,52 @@ namespace FEXCore::Allocator {
|
||||
|
||||
FEX_DEFAULT_VISIBILITY size_t DetermineVASize();
|
||||
|
||||
#ifdef GLIBC_ALLOCATOR_FAULT
|
||||
// Glibc hooks should only fault once we are in main.
|
||||
// Required since glibc allocator hooking will catch things before FEX has control.
|
||||
FEX_DEFAULT_VISIBILITY void SetupFaultEvaluate();
|
||||
// Glibc hook faulting needs to be disabled when leaving main.
|
||||
// Required since glibc does some state teardown after main.
|
||||
FEX_DEFAULT_VISIBILITY void ClearFaultEvaluate();
|
||||
|
||||
class FEX_DEFAULT_VISIBILITY YesIKnowImNotSupposedToUseTheGlibcAllocator final {
|
||||
public:
|
||||
FEX_DEFAULT_VISIBILITY YesIKnowImNotSupposedToUseTheGlibcAllocator();
|
||||
FEX_DEFAULT_VISIBILITY ~YesIKnowImNotSupposedToUseTheGlibcAllocator();
|
||||
FEX_DEFAULT_VISIBILITY static void HardDisable();
|
||||
};
|
||||
|
||||
class FEX_DEFAULT_VISIBILITY GLIBCScopedFault final {
|
||||
public:
|
||||
GLIBCScopedFault() {
|
||||
FEXCore::Allocator::SetupFaultEvaluate();
|
||||
}
|
||||
~GLIBCScopedFault() {
|
||||
FEXCore::Allocator::ClearFaultEvaluate();
|
||||
}
|
||||
};
|
||||
#else
|
||||
FEX_DEFAULT_VISIBILITY inline void SetupFaultEvaluate() {}
|
||||
FEX_DEFAULT_VISIBILITY inline void ClearFaultEvaluate() {}
|
||||
|
||||
class FEX_DEFAULT_VISIBILITY YesIKnowImNotSupposedToUseTheGlibcAllocator final {
|
||||
public:
|
||||
FEX_DEFAULT_VISIBILITY YesIKnowImNotSupposedToUseTheGlibcAllocator() {}
|
||||
FEX_DEFAULT_VISIBILITY ~YesIKnowImNotSupposedToUseTheGlibcAllocator() {}
|
||||
FEX_DEFAULT_VISIBILITY static inline void HardDisable() {}
|
||||
};
|
||||
|
||||
class FEX_DEFAULT_VISIBILITY GLIBCScopedFault final {
|
||||
public:
|
||||
GLIBCScopedFault() {
|
||||
// nop
|
||||
}
|
||||
~GLIBCScopedFault() {
|
||||
// nop
|
||||
}
|
||||
};
|
||||
#endif
|
||||
|
||||
struct MemoryRegion {
|
||||
void *Ptr;
|
||||
size_t Size;
|
||||
|
@ -30,4 +30,16 @@ namespace FEXCore::Allocator {
|
||||
FEX_DEFAULT_VISIBILITY extern FREE_Hook free;
|
||||
FEX_DEFAULT_VISIBILITY extern MALLOC_USABLE_SIZE_Hook malloc_usable_size;
|
||||
FEX_DEFAULT_VISIBILITY extern ALIGNED_ALLOC_Hook aligned_alloc;
|
||||
|
||||
struct FEXAllocOperators {
|
||||
FEXAllocOperators() = default;
|
||||
|
||||
void *operator new(size_t size) {
|
||||
return FEXCore::Allocator::malloc(size);
|
||||
}
|
||||
|
||||
void operator delete(void *ptr) {
|
||||
return FEXCore::Allocator::free(ptr);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
@ -1,8 +1,8 @@
|
||||
#pragma once
|
||||
|
||||
#include <cstddef>
|
||||
#include <memory>
|
||||
#include <FEXCore/Utils/LogManager.h>
|
||||
#include <FEXCore/fextl/memory.h>
|
||||
|
||||
namespace FEXCore {
|
||||
|
||||
@ -17,7 +17,7 @@ namespace FEXCore {
|
||||
static constexpr size_t Size = _Size;
|
||||
|
||||
T Items[Size];
|
||||
std::unique_ptr<BucketList<Size, T>> Next;
|
||||
fextl::unique_ptr<BucketList<Size, T>> Next;
|
||||
|
||||
void Clear() {
|
||||
Items[0] = T{};
|
||||
@ -96,7 +96,7 @@ namespace FEXCore {
|
||||
if (i < (Size-1)) {
|
||||
that->Items[i+1] = T{};
|
||||
} else {
|
||||
that->Next = std::make_unique<BucketList<Size, T>>();
|
||||
that->Next = fextl::make_unique<BucketList<Size, T>>();
|
||||
}
|
||||
}
|
||||
void Erase(T Val) {
|
||||
|
@ -63,7 +63,12 @@ namespace FEXCore::Utils {
|
||||
|
||||
using BufferOwnedFlag = std::atomic<ClientFlags>;
|
||||
|
||||
struct MemoryBuffer {
|
||||
struct MemoryBuffer : public FEXCore::Allocator::FEXAllocOperators {
|
||||
MemoryBuffer(void* Ptr, size_t Size, std::chrono::time_point<ClockType> LastUsed)
|
||||
: Ptr {Ptr}
|
||||
, Size {Size}
|
||||
, LastUsed {LastUsed} {}
|
||||
|
||||
void* Ptr;
|
||||
size_t Size;
|
||||
std::atomic<std::chrono::time_point<ClockType>> LastUsed;
|
||||
|
@ -1,12 +1,13 @@
|
||||
#pragma once
|
||||
#include <FEXCore/fextl/memory.h>
|
||||
|
||||
#include <functional>
|
||||
#include <memory>
|
||||
|
||||
namespace FEXCore::Threads {
|
||||
using ThreadFunc = void*(*)(void* user_ptr);
|
||||
|
||||
class Thread;
|
||||
using CreateThreadFunc = std::function<std::unique_ptr<Thread>(ThreadFunc Func, void* Arg)>;
|
||||
using CreateThreadFunc = std::function<fextl::unique_ptr<Thread>(ThreadFunc Func, void* Arg)>;
|
||||
using CleanupAfterForkFunc = std::function<void()>;
|
||||
|
||||
struct Pointers {
|
||||
@ -27,7 +28,7 @@ namespace FEXCore::Threads {
|
||||
* @name Calls provided API functions
|
||||
* @{ */
|
||||
|
||||
static std::unique_ptr<Thread> Create(
|
||||
static fextl::unique_ptr<Thread> Create(
|
||||
ThreadFunc Func,
|
||||
void* Arg);
|
||||
|
||||
|
8
External/FEXCore/include/FEXCore/fextl/fmt.h
vendored
8
External/FEXCore/include/FEXCore/fextl/fmt.h
vendored
@ -3,6 +3,7 @@
|
||||
#include <FEXCore/fextl/string.h>
|
||||
|
||||
#include <fmt/format.h>
|
||||
#include <unistd.h>
|
||||
|
||||
namespace fextl::fmt {
|
||||
template <typename T, size_t SIZE = ::fmt::inline_buffer_size,
|
||||
@ -36,4 +37,11 @@ namespace fextl::fmt {
|
||||
-> fextl::string {
|
||||
return fextl::fmt::vformat(fmt, ::fmt::make_format_args(args...));
|
||||
}
|
||||
|
||||
template <typename... T>
|
||||
FMT_INLINE auto print(::fmt::format_string<T...> fmt, T&&... args)
|
||||
-> void {
|
||||
auto String = fextl::fmt::vformat(fmt, ::fmt::make_format_args(args...));
|
||||
write(STDERR_FILENO, String.c_str(), String.size());
|
||||
}
|
||||
}
|
||||
|
33
External/FEXCore/include/FEXCore/fextl/memory.h
vendored
Normal file
33
External/FEXCore/include/FEXCore/fextl/memory.h
vendored
Normal file
@ -0,0 +1,33 @@
|
||||
#pragma once
|
||||
#include <FEXCore/fextl/allocator.h>
|
||||
|
||||
#include <memory>
|
||||
#include <new>
|
||||
#include <fmt/format.h>
|
||||
|
||||
namespace fextl {
|
||||
template<class T>
|
||||
struct default_delete : public std::default_delete<T> {
|
||||
void operator()(T* ptr) const {
|
||||
std::destroy_at(ptr);
|
||||
FEXCore::Allocator::free(ptr);
|
||||
}
|
||||
|
||||
template<typename U>
|
||||
requires (std::is_base_of_v<U, T>)
|
||||
operator fextl::default_delete<U>() {
|
||||
return fextl::default_delete<U>();
|
||||
}
|
||||
};
|
||||
|
||||
template<class T, class Deleter = fextl::default_delete<T>>
|
||||
using unique_ptr = std::unique_ptr<T, Deleter>;
|
||||
|
||||
template<class T, class... Args>
|
||||
fextl::unique_ptr<T> make_unique(Args&&... args) {
|
||||
auto ptr = FEXCore::Allocator::aligned_alloc(std::alignment_of_v<T>, sizeof(T));
|
||||
auto Result = ::new (ptr) T (std::forward<Args>(args)...);
|
||||
return fextl::unique_ptr<T>(Result);
|
||||
}
|
||||
}
|
||||
|
77
External/FEXCore/include/FEXCore/fextl/memory_resource.h
vendored
Normal file
77
External/FEXCore/include/FEXCore/fextl/memory_resource.h
vendored
Normal file
@ -0,0 +1,77 @@
|
||||
#pragma once
|
||||
#include <FEXCore/Utils/MathUtils.h>
|
||||
#include <FEXCore/Utils/LogManager.h>
|
||||
#include <FEXCore/fextl/allocator.h>
|
||||
|
||||
#include <memory_resource>
|
||||
#include <fmt/format.h>
|
||||
|
||||
namespace fextl {
|
||||
namespace pmr {
|
||||
class default_resource : public std::pmr::memory_resource {
|
||||
private:
|
||||
void* do_allocate( std::size_t bytes, std::size_t alignment ) override {
|
||||
return FEXCore::Allocator::memalign(alignment, bytes);
|
||||
}
|
||||
|
||||
void do_deallocate( void* p, std::size_t bytes, std::size_t alignment ) override {
|
||||
return FEXCore::Allocator::free(p);
|
||||
}
|
||||
|
||||
bool do_is_equal( const std::pmr::memory_resource& other ) const noexcept override {
|
||||
return this == &other;
|
||||
}
|
||||
};
|
||||
|
||||
FEX_DEFAULT_VISIBILITY std::pmr::memory_resource* get_default_resource();
|
||||
|
||||
/**
|
||||
* @brief This is similar to the std::pmr::monotonic_buffer_resource.
|
||||
*
|
||||
* The difference is that class doesn't have ownership of the backing memory and
|
||||
* it also doesn't have any growth factor.
|
||||
*
|
||||
* If the amount of memory allocated is overrun then this will overwrite memory unless assertions are enabled.
|
||||
*
|
||||
* Ensure that you know how much memory you're going to use before using this class.
|
||||
*/
|
||||
class fixed_size_monotonic_buffer_resource final : public std::pmr::memory_resource {
|
||||
public:
|
||||
fixed_size_monotonic_buffer_resource(void* Base, [[maybe_unused]] size_t Size)
|
||||
: Ptr {reinterpret_cast<uint64_t>(Base)}
|
||||
#if defined(ASSERTIONS_ENABLED) && ASSERTIONS_ENABLED
|
||||
, PtrEnd {reinterpret_cast<uint64_t>(Base) + Size}
|
||||
, Size {Size}
|
||||
#endif
|
||||
{}
|
||||
void* do_allocate( std::size_t bytes, std::size_t alignment ) override {
|
||||
uint64_t NewPtr = FEXCore::AlignUp((uint64_t)Ptr, alignment);
|
||||
Ptr = NewPtr + bytes;
|
||||
#if defined(ASSERTIONS_ENABLED) && ASSERTIONS_ENABLED
|
||||
if (Ptr >= PtrEnd) {
|
||||
LogMan::Msg::AFmt("Fail: Only allocated: {} ({} this time) bytes. Tried allocating at ptr offset: {}.\n",
|
||||
Size,
|
||||
bytes,
|
||||
(uint64_t)(Ptr - (PtrEnd - Size)));
|
||||
FEX_TRAP_EXECUTION;
|
||||
}
|
||||
#endif
|
||||
return reinterpret_cast<void*>(NewPtr);
|
||||
}
|
||||
|
||||
void do_deallocate( void* p, std::size_t bytes, std::size_t alignment ) override {
|
||||
// noop
|
||||
}
|
||||
|
||||
bool do_is_equal( const std::pmr::memory_resource& other ) const noexcept override {
|
||||
return this == &other;
|
||||
}
|
||||
private:
|
||||
uint64_t Ptr;
|
||||
#if defined(ASSERTIONS_ENABLED) && ASSERTIONS_ENABLED
|
||||
uint64_t PtrEnd;
|
||||
size_t Size;
|
||||
#endif
|
||||
};
|
||||
}
|
||||
}
|
9
External/FEXCore/include/FEXCore/fextl/robin_map.h
vendored
Normal file
9
External/FEXCore/include/FEXCore/fextl/robin_map.h
vendored
Normal file
@ -0,0 +1,9 @@
|
||||
#pragma once
|
||||
#include <FEXCore/fextl/allocator.h>
|
||||
|
||||
#include <tsl/robin_map.h>
|
||||
|
||||
namespace fextl {
|
||||
template<class Key, class T, class Hash = std::hash<Key>, class KeyEqual = std::equal_to<Key>, class Allocator = fextl::FEXAlloc<std::pair<const Key, T>>>
|
||||
using robin_map = tsl::robin_map<Key, T, Hash, KeyEqual, Allocator>;
|
||||
}
|
@ -6,4 +6,7 @@
|
||||
namespace fextl {
|
||||
template<class Key, class T, class Hash = std::hash<Key>, class KeyEqual = std::equal_to<Key>, class Allocator = fextl::FEXAlloc<std::pair<const Key, T>>>
|
||||
using unordered_map = std::unordered_map<Key, T, Hash, KeyEqual, Allocator>;
|
||||
|
||||
template<class Key, class T, class Hash = std::hash<Key>, class KeyEqual = std::equal_to<Key>, class Allocator = fextl::FEXAlloc<std::pair<const Key, T>>>
|
||||
using unordered_multimap = std::unordered_multimap<Key, T, Hash, KeyEqual, Allocator>;
|
||||
}
|
||||
|
1
External/cpp-optparse
vendored
1
External/cpp-optparse
vendored
@ -1 +0,0 @@
|
||||
Subproject commit 2e480985bd5b024d4659988dc30c94ac24b4b14a
|
2
External/xbyak
vendored
2
External/xbyak
vendored
@ -1 +1 @@
|
||||
Subproject commit b0f0c7805ad16d9abbac0f8101cc226669983b57
|
||||
Subproject commit 5f8c0488bab7a5e1c8cee831c3b6a5a884e10df8
|
@ -1,6 +1,15 @@
|
||||
#pragma once
|
||||
#include <FEXCore/fextl/fmt.h>
|
||||
#include <FEXCore/fextl/list.h>
|
||||
#include <FEXCore/fextl/memory_resource.h>
|
||||
#include <FEXCore/fextl/string.h>
|
||||
|
||||
#include <algorithm>
|
||||
#include <fcntl.h>
|
||||
#include <memory_resource>
|
||||
#include <string>
|
||||
#include <sys/sendfile.h>
|
||||
#include <sys/stat.h>
|
||||
#include <unistd.h>
|
||||
|
||||
namespace FHU::Filesystem {
|
||||
@ -14,4 +23,283 @@ namespace FHU::Filesystem {
|
||||
inline bool Exists(const char *Path) {
|
||||
return access(Path, F_OK) == 0;
|
||||
}
|
||||
|
||||
inline bool Exists(const fextl::string &Path) {
|
||||
return access(Path.c_str(), F_OK) == 0;
|
||||
}
|
||||
|
||||
enum class CreateDirectoryResult {
|
||||
CREATED,
|
||||
EXISTS,
|
||||
ERROR,
|
||||
};
|
||||
/**
|
||||
* @brief Creates a directory at the provided path.
|
||||
*
|
||||
* @param Path The path to create a directory at.
|
||||
*
|
||||
* @return Result enum depending.
|
||||
*/
|
||||
inline CreateDirectoryResult CreateDirectory(const fextl::string &Path) {
|
||||
auto Result = ::mkdir(Path.c_str(), 0777);
|
||||
if (Result == 0) {
|
||||
return CreateDirectoryResult::CREATED;
|
||||
}
|
||||
|
||||
if (Result == -1 && errno == EEXIST) {
|
||||
// If it exists, we need to check if it is a file or folder.
|
||||
struct stat buf;
|
||||
if (stat(Path.c_str(), &buf) == 0) {
|
||||
// Check to see if the path is a file or folder. Following symlinks.
|
||||
return S_ISDIR(buf.st_mode) ?
|
||||
CreateDirectoryResult::EXISTS :
|
||||
CreateDirectoryResult::ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
// Couldn't create, or the path that existed wasn't a folder.
|
||||
return CreateDirectoryResult::ERROR;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Creates a directory tree with the provided path.
|
||||
*
|
||||
* @param Path The path to create a tree at.
|
||||
*
|
||||
* @return True if the directory tree was created or already exists.
|
||||
*/
|
||||
inline bool CreateDirectories(const fextl::string &Path) {
|
||||
// Try to create the directory initially.
|
||||
if (CreateDirectory(Path) != CreateDirectoryResult::ERROR) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// Walk the path in reverse and create paths as we go.
|
||||
fextl::string TmpPath {Path.substr(0, Path.rfind('/', Path.size() - 1))};
|
||||
if (!TmpPath.empty() && CreateDirectories(TmpPath)) {
|
||||
return CreateDirectory(Path) != CreateDirectoryResult::ERROR;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Extracts the filename component from a file path.
|
||||
*
|
||||
* @param Path The path to create a directory at.
|
||||
*
|
||||
* @return The filename component of the path.
|
||||
*/
|
||||
inline fextl::string GetFilename(const fextl::string &Path) {
|
||||
auto LastSeparator = Path.rfind('/');
|
||||
if (LastSeparator == fextl::string::npos) {
|
||||
// No separator. Likely relative `.`, `..`, `<Application Name>`, or empty string.
|
||||
return Path;
|
||||
}
|
||||
|
||||
return Path.substr(LastSeparator + 1);
|
||||
}
|
||||
|
||||
inline fextl::string ParentPath(const fextl::string &Path) {
|
||||
auto LastSeparator = Path.rfind('/');
|
||||
|
||||
if (LastSeparator == fextl::string::npos) {
|
||||
// No separator. Likely relative `.`, `..`, `<Application Name>`, or empty string.
|
||||
if (Path == "." || Path == "..") {
|
||||
// In this edge-case, return nothing to match std::filesystem::path::parent_path behaviour.
|
||||
return {};
|
||||
}
|
||||
return Path;
|
||||
}
|
||||
|
||||
if (LastSeparator == 0) {
|
||||
// In the case of root, just return.
|
||||
return "/";
|
||||
}
|
||||
|
||||
auto SubString = Path.substr(0, LastSeparator);
|
||||
|
||||
while (SubString.size() > 1 && SubString.ends_with("/")) {
|
||||
// If the substring still ended with `/` then we need to string that off as well.
|
||||
--LastSeparator;
|
||||
SubString = Path.substr(0, LastSeparator);
|
||||
}
|
||||
|
||||
return SubString;
|
||||
}
|
||||
|
||||
inline bool IsRelative(const fextl::string &Path) {
|
||||
return !Path.starts_with('/');
|
||||
}
|
||||
|
||||
inline bool IsAbsolute(const fextl::string &Path) {
|
||||
return Path.starts_with('/');
|
||||
}
|
||||
|
||||
enum class CopyOptions {
|
||||
NONE,
|
||||
SKIP_EXISTING,
|
||||
OVERWRITE_EXISTING,
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Copy a file from a location to another
|
||||
*
|
||||
* Behaves similarly to std::filesystem::copy_file but with less copy options.
|
||||
*
|
||||
* @param From Source file location.
|
||||
* @param To Destination file location.
|
||||
* @param Options Copy options.
|
||||
*
|
||||
* @return True if the copy succeeded, false otherwise.
|
||||
*/
|
||||
inline bool CopyFile(const fextl::string &From, const fextl::string &To, CopyOptions Options = CopyOptions::NONE) {
|
||||
const bool DestExists = Exists(To);
|
||||
if (Options == CopyOptions::SKIP_EXISTING && DestExists) {
|
||||
// If the destination file exists already and the skip existing flag is set then
|
||||
// return true without error.
|
||||
return true;
|
||||
}
|
||||
|
||||
if (Options == CopyOptions::OVERWRITE_EXISTING && DestExists) {
|
||||
// If we are overwriting and the file exists then we want to use `sendfile` to overwrite
|
||||
int SourceFD = open(From.c_str(), O_RDONLY | O_CLOEXEC);
|
||||
if (SourceFD == -1) {
|
||||
return false;
|
||||
}
|
||||
|
||||
int DestinationFD = open(To.c_str(), O_WRONLY | O_CREAT | O_TRUNC, 0200);
|
||||
if (DestinationFD == -1) {
|
||||
close(SourceFD);
|
||||
return false;
|
||||
}
|
||||
|
||||
struct stat buf;
|
||||
if (fstat(SourceFD, &buf) != 0) {
|
||||
close(DestinationFD);
|
||||
close(SourceFD);
|
||||
return false;
|
||||
}
|
||||
|
||||
// Set the destination permissions to the original source permissions.
|
||||
if (fchmod(DestinationFD, buf.st_mode) != 0) {
|
||||
close(DestinationFD);
|
||||
close(SourceFD);
|
||||
return false;
|
||||
}
|
||||
bool Result = sendfile(DestinationFD, SourceFD, nullptr, buf.st_size) == buf.st_size;
|
||||
close(DestinationFD);
|
||||
close(SourceFD);
|
||||
return Result;
|
||||
}
|
||||
|
||||
if (!DestExists) {
|
||||
// If the destination doesn't exist then just use rename.
|
||||
return rename(From.c_str(), To.c_str()) == 0;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
inline fextl::string LexicallyNormal(const fextl::string &Path) {
|
||||
const auto PathSize = Path.size();
|
||||
|
||||
// Early exit on empty paths.
|
||||
if (PathSize == 0) {
|
||||
return {};
|
||||
}
|
||||
|
||||
const auto IsAbsolutePath = IsAbsolute(Path);
|
||||
const auto EndsWithSeparator = Path.ends_with('/');
|
||||
// Count the number of separators up front
|
||||
const auto SeparatorCount = std::count(Path.begin(), Path.end(), '/');
|
||||
|
||||
// Use std::list to store path elements to avoid iterator invalidation on insert/erase.
|
||||
// The list is allocated on stack to be more optimal. The size is determined by the
|
||||
// maximum number of list objects (separator count plus 2) multiplied by the list
|
||||
// element size (32-bytes per element: the string_view itself and the prev/next pointers).
|
||||
size_t DataSize = (sizeof(std::string_view) + sizeof(void*) * 2) * (SeparatorCount + 2);
|
||||
void *Data = alloca(DataSize);
|
||||
fextl::pmr::fixed_size_monotonic_buffer_resource mbr(Data, DataSize);
|
||||
std::pmr::polymorphic_allocator pa {&mbr};
|
||||
std::pmr::list<std::string_view> Parts{pa};
|
||||
|
||||
size_t CurrentOffset{};
|
||||
do {
|
||||
auto FoundSeperator = Path.find('/', CurrentOffset);
|
||||
if (FoundSeperator == Path.npos) {
|
||||
FoundSeperator = PathSize;
|
||||
}
|
||||
|
||||
const auto Begin = Path.begin() + CurrentOffset;
|
||||
const auto End = Path.begin() + FoundSeperator;
|
||||
const auto Size = End - Begin;
|
||||
|
||||
// Only insert parts that contain data.
|
||||
if (Size != 0) {
|
||||
Parts.emplace_back(std::string_view(Begin, End));
|
||||
}
|
||||
|
||||
if (Size == 0) {
|
||||
// If the view is empty, skip over the separator.
|
||||
FoundSeperator += 1;
|
||||
}
|
||||
|
||||
CurrentOffset = FoundSeperator;
|
||||
} while (CurrentOffset != PathSize);
|
||||
|
||||
size_t CurrentIterDistance{};
|
||||
for (auto iter = Parts.begin(); iter != Parts.end();) {
|
||||
auto &Part = *iter;
|
||||
if (Part == ".") {
|
||||
// Erase '.' directory parts if not at root.
|
||||
if (CurrentIterDistance > 0 || IsAbsolutePath) {
|
||||
// Erasing this iterator, don't increase iter distances
|
||||
iter = Parts.erase(iter);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
if (Part == "..") {
|
||||
if (CurrentIterDistance > 0) {
|
||||
// If not at root then remove both this iterator and the previous one.
|
||||
// ONLY if the previous iterator is also not ".."
|
||||
//
|
||||
// If the previous iterator is '.' then /only/ erase the previous iterator.
|
||||
auto PreviousIter = iter;
|
||||
--PreviousIter;
|
||||
|
||||
if (*PreviousIter == ".") {
|
||||
// Erasing the previous iterator, iterator distance has subtracted by one
|
||||
--CurrentIterDistance;
|
||||
Parts.erase(PreviousIter);
|
||||
}
|
||||
else if (*PreviousIter != "..") {
|
||||
// Erasing the previous iterator, iterator distance has subtracted by one
|
||||
// Also erasing current iterator, which means iterator distance also doesn't increase by one.
|
||||
--CurrentIterDistance;
|
||||
Parts.erase(PreviousIter);
|
||||
iter = Parts.erase(iter);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
else if (IsAbsolutePath) {
|
||||
// `..` at the base. Just remove this
|
||||
iter = Parts.erase(iter);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
// Interator distance increased by one.
|
||||
++CurrentIterDistance;
|
||||
++iter;
|
||||
}
|
||||
|
||||
|
||||
// Add a final separator unless the last element is ellipses.
|
||||
const bool NeedsFinalSeparator = EndsWithSeparator && (!Parts.empty() && Parts.back() != "." && Parts.back() != "..");
|
||||
return fextl::fmt::format("{}{}{}",
|
||||
IsAbsolutePath ? "/" : "",
|
||||
fmt::join(Parts, "/"),
|
||||
NeedsFinalSeparator ? "/" : "");
|
||||
}
|
||||
}
|
||||
|
@ -1,13 +1,14 @@
|
||||
#pragma once
|
||||
#include <FEXCore/fextl/string.h>
|
||||
|
||||
#include <fcntl.h>
|
||||
#include <string>
|
||||
#include <sys/stat.h>
|
||||
#include <span>
|
||||
#include <unistd.h>
|
||||
|
||||
namespace FHU::Symlinks {
|
||||
// Checks to see if a filepath is a symlink.
|
||||
inline bool IsSymlink(const std::string &Filename) {
|
||||
inline bool IsSymlink(const fextl::string &Filename) {
|
||||
struct stat Buffer{};
|
||||
int Result = lstat(Filename.c_str(), &Buffer);
|
||||
return Result == 0 && S_ISLNK(Buffer.st_mode);
|
||||
@ -17,7 +18,7 @@ inline bool IsSymlink(const std::string &Filename) {
|
||||
// Doesn't handle recursive symlinks.
|
||||
// Doesn't append null terminator character.
|
||||
// Returns a string_view of the resolved path, or an empty view on error.
|
||||
inline std::string_view ResolveSymlink(const std::string &Filename, std::span<char> ResultBuffer) {
|
||||
inline std::string_view ResolveSymlink(const fextl::string &Filename, std::span<char> ResultBuffer) {
|
||||
ssize_t Result = readlink(Filename.c_str(), ResultBuffer.data(), ResultBuffer.size());
|
||||
if (Result == -1) {
|
||||
return {};
|
||||
|
@ -3,7 +3,7 @@
|
||||
#include <FEXCore/fextl/string.h>
|
||||
#include <FEXCore/fextl/vector.h>
|
||||
|
||||
#include "OptionParser.h"
|
||||
#include "cpp-optparse/OptionParser.h"
|
||||
#include "git_version.h"
|
||||
|
||||
#include <stdint.h>
|
||||
@ -12,7 +12,7 @@ namespace FEX::ArgLoader {
|
||||
fextl::vector<fextl::string> RemainingArgs;
|
||||
fextl::vector<fextl::string> ProgramArguments;
|
||||
|
||||
static std::string Version = "FEX-Emu (" GIT_DESCRIBE_STRING ") ";
|
||||
static fextl::string Version = "FEX-Emu (" GIT_DESCRIBE_STRING ") ";
|
||||
void FEX::ArgLoader::ArgLoader::Load() {
|
||||
optparse::OptionParser Parser{};
|
||||
Parser.version(Version);
|
||||
@ -39,12 +39,8 @@ namespace FEX::ArgLoader {
|
||||
using uint32 = uint32_t;
|
||||
#define AFTER_PARSE
|
||||
#include <FEXCore/Config/ConfigOptions.inl>
|
||||
// TODO: Convert cpp-optparse over to fextl::vector
|
||||
auto ParserArgs = Parser.args();
|
||||
auto ParsedArgs = Parser.parsed_args();
|
||||
|
||||
RemainingArgs.insert(RemainingArgs.begin(), ParserArgs.begin(), ParserArgs.end());
|
||||
ProgramArguments.insert(ProgramArguments.begin(), ParsedArgs.begin(), ParsedArgs.end());
|
||||
RemainingArgs = Parser.args();
|
||||
ProgramArguments = Parser.parsed_args();
|
||||
}
|
||||
|
||||
void LoadWithoutArguments(int _argc, char **_argv) {
|
||||
|
@ -1,3 +1,5 @@
|
||||
add_subdirectory(cpp-optparse/)
|
||||
|
||||
set(NAME Common)
|
||||
set(SRCS
|
||||
ArgumentLoader.cpp
|
||||
|
@ -5,6 +5,7 @@
|
||||
#include <FEXCore/fextl/fmt.h>
|
||||
#include <FEXCore/fextl/map.h>
|
||||
#include <FEXCore/fextl/string.h>
|
||||
#include <FEXHeaderUtils/Filesystem.h>
|
||||
#include <FEXHeaderUtils/SymlinkChecks.h>
|
||||
|
||||
#include <cstring>
|
||||
@ -58,7 +59,11 @@ namespace FEX::Config {
|
||||
// If the program name isn't resolved to an absolute path then glibc breaks inside it's `_dl_get_origin` function.
|
||||
// This is because we rewrite `/proc/self/exe` to the absolute program path calculated in here.
|
||||
if (!Program.starts_with('/')) {
|
||||
Program = std::filesystem::canonical(std::move(Program)).string();
|
||||
char ExistsTempPath[PATH_MAX];
|
||||
char *RealPath = realpath(Program.c_str(), ExistsTempPath);
|
||||
if (RealPath) {
|
||||
Program = RealPath;
|
||||
}
|
||||
}
|
||||
|
||||
// If FEX was invoked through an FD path (either binfmt_misc or execveat) then we need to check the
|
||||
@ -89,9 +94,9 @@ namespace FEX::Config {
|
||||
// This symlink will be in the style of `/dev/fd/<FD>`.
|
||||
//
|
||||
// If the argument /is/ a symlink then resolve its path to get the original application name.
|
||||
if (FHU::Symlinks::IsSymlink(fextl::string_from_string(Program))) {
|
||||
if (FHU::Symlinks::IsSymlink(Program)) {
|
||||
char Filename[PATH_MAX];
|
||||
auto SymlinkPath = FHU::Symlinks::ResolveSymlink(fextl::string_from_string(Program), Filename);
|
||||
auto SymlinkPath = FHU::Symlinks::ResolveSymlink(Program, Filename);
|
||||
if (SymlinkPath.starts_with('/')) {
|
||||
// This file was executed through an FD.
|
||||
// Remove the ` (deleted)` text if the file was deleted after the fact.
|
||||
@ -120,7 +125,7 @@ namespace FEX::Config {
|
||||
FEX::ArgLoader::LoadWithoutArguments(argc, argv);
|
||||
}
|
||||
else {
|
||||
FEXCore::Config::AddLayer(std::make_unique<FEX::ArgLoader::ArgLoader>(argc, argv));
|
||||
FEXCore::Config::AddLayer(fextl::make_unique<FEX::ArgLoader::ArgLoader>(argc, argv));
|
||||
}
|
||||
|
||||
FEXCore::Config::AddLayer(FEXCore::Config::CreateEnvironmentLayer(envp));
|
||||
@ -138,9 +143,9 @@ namespace FEX::Config {
|
||||
fextl::string& Program = Args[0];
|
||||
|
||||
bool Wine = false;
|
||||
std::filesystem::path ProgramName;
|
||||
fextl::string ProgramName;
|
||||
for (size_t CurrentProgramNameIndex = 0; CurrentProgramNameIndex < Args.size(); ++CurrentProgramNameIndex) {
|
||||
auto CurrentProgramName = std::filesystem::path(Args[CurrentProgramNameIndex]).filename();
|
||||
auto CurrentProgramName = FHU::Filesystem::GetFilename(Args[CurrentProgramNameIndex]);
|
||||
|
||||
if (CurrentProgramName == "wine-preloader" ||
|
||||
CurrentProgramName == "wine64-preloader") {
|
||||
@ -162,10 +167,10 @@ namespace FEX::Config {
|
||||
else {
|
||||
if (Wine == true) {
|
||||
// If this was path separated with '\' then we need to check that.
|
||||
auto WinSeparator = CurrentProgramName.string().find_last_of('\\');
|
||||
if (WinSeparator != CurrentProgramName.string().npos) {
|
||||
auto WinSeparator = CurrentProgramName.find_last_of('\\');
|
||||
if (WinSeparator != CurrentProgramName.npos) {
|
||||
// Used windows separators
|
||||
CurrentProgramName = CurrentProgramName.string().substr(WinSeparator + 1);
|
||||
CurrentProgramName = CurrentProgramName.substr(WinSeparator + 1);
|
||||
}
|
||||
}
|
||||
|
||||
@ -176,8 +181,8 @@ namespace FEX::Config {
|
||||
}
|
||||
}
|
||||
|
||||
FEXCore::Config::AddLayer(FEXCore::Config::CreateAppLayer(fextl::string_from_path(ProgramName), FEXCore::Config::LayerType::LAYER_GLOBAL_APP));
|
||||
FEXCore::Config::AddLayer(FEXCore::Config::CreateAppLayer(fextl::string_from_path(ProgramName), FEXCore::Config::LayerType::LAYER_LOCAL_APP));
|
||||
FEXCore::Config::AddLayer(FEXCore::Config::CreateAppLayer(ProgramName, FEXCore::Config::LayerType::LAYER_GLOBAL_APP));
|
||||
FEXCore::Config::AddLayer(FEXCore::Config::CreateAppLayer(ProgramName, FEXCore::Config::LayerType::LAYER_LOCAL_APP));
|
||||
|
||||
auto SteamID = getenv("SteamAppId");
|
||||
if (SteamID) {
|
||||
@ -188,8 +193,7 @@ namespace FEX::Config {
|
||||
FEXCore::Config::AddLayer(FEXCore::Config::CreateAppLayer(SteamAppName, FEXCore::Config::LayerType::LAYER_LOCAL_STEAM_APP));
|
||||
}
|
||||
|
||||
// TODO: No need for conversion once Config uses fextl.
|
||||
return ApplicationNames{std::move(Program), fextl::string_from_path(ProgramName)};
|
||||
return ApplicationNames{std::move(Program), std::move(ProgramName)};
|
||||
}
|
||||
return {};
|
||||
}
|
||||
|
@ -1,5 +1,6 @@
|
||||
#pragma once
|
||||
|
||||
#include <FEXCore/Utils/Allocator.h>
|
||||
#include <FEXCore/Utils/LogManager.h>
|
||||
#include <FEXCore/fextl/string.h>
|
||||
|
||||
@ -10,19 +11,6 @@
|
||||
#include <unistd.h>
|
||||
|
||||
namespace FEX {
|
||||
[[maybe_unused]]
|
||||
static
|
||||
std::optional<fextl::string> get_fdpath(int fd) {
|
||||
char SymlinkPath[PATH_MAX];
|
||||
std::filesystem::path Path = std::filesystem::path("/proc/self/fd") / std::to_string(fd);
|
||||
int Result = readlinkat(AT_FDCWD, Path.c_str(), SymlinkPath, sizeof(SymlinkPath));
|
||||
if (Result != -1) {
|
||||
return fextl::string(SymlinkPath, Result);
|
||||
}
|
||||
|
||||
// Not fatal if an FD doesn't point to a file
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
inline
|
||||
int get_fdpath(int fd, char *SymlinkPath) {
|
||||
|
@ -7,6 +7,7 @@
|
||||
#include <FEXCore/fextl/fmt.h>
|
||||
#include <FEXCore/fextl/string.h>
|
||||
#include <FEXCore/fextl/vector.h>
|
||||
#include <FEXHeaderUtils/Filesystem.h>
|
||||
|
||||
#include <fcntl.h>
|
||||
#include <filesystem>
|
||||
@ -211,10 +212,10 @@ namespace FEXServerClient {
|
||||
return -1;
|
||||
}
|
||||
|
||||
fextl::string FEXServerPath = fextl::string_from_path(std::filesystem::path(InterpreterPath).parent_path()) + "/FEXServer";
|
||||
fextl::string FEXServerPath = FHU::Filesystem::ParentPath(InterpreterPath) + "/FEXServer";
|
||||
// Check if a local FEXServer next to FEXInterpreter exists
|
||||
// If it does then it takes priority over the installed one
|
||||
if (!std::filesystem::exists(FEXServerPath)) {
|
||||
if (!FHU::Filesystem::Exists(FEXServerPath)) {
|
||||
FEXServerPath = "FEXServer";
|
||||
}
|
||||
|
||||
|
1
Source/Common/cpp-optparse
Submodule
1
Source/Common/cpp-optparse
Submodule
@ -0,0 +1 @@
|
||||
Subproject commit 1f3b88a1ba3c4c6302a096d7e9002982e8811cb7
|
@ -66,8 +66,7 @@ class ELFCodeLoader final : public FEXCore::CodeLoader {
|
||||
return PAGE_ALIGN(last->p_vaddr + last->p_memsz);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
bool MapFile(const ELFParser& file, uintptr_t Base, const Elf64_Phdr &Header, int prot, int flags, T Mapper) {
|
||||
bool MapFile(const ELFParser& file, uintptr_t Base, const Elf64_Phdr &Header, int prot, int flags, FEX::HLE::SyscallHandler *const Handler) {
|
||||
|
||||
auto addr = Base + PAGE_START(Header.p_vaddr);
|
||||
auto size = Header.p_filesz + PAGE_OFFSET(Header.p_vaddr);
|
||||
@ -80,16 +79,17 @@ class ELFCodeLoader final : public FEXCore::CodeLoader {
|
||||
return true;
|
||||
}
|
||||
|
||||
void *rv = Mapper((void*)addr, size, prot, flags, file.fd, off);
|
||||
void *rv = Handler->GuestMmap((void*)addr, size, prot, flags, file.fd, off);
|
||||
|
||||
if (rv == MAP_FAILED) {
|
||||
// uhoh, something went wrong
|
||||
LogMan::Msg::EFmt("MapFile: Some elf mapping failed, {}, fd: {}\n", errno, file.fd);
|
||||
return false;
|
||||
} else {
|
||||
auto Filename = FEX::get_fdpath(file.fd);
|
||||
if (Filename.has_value()) {
|
||||
Sections.push_back({Base, (uintptr_t)rv, size, (off_t)off, Filename.value(), (prot & PROT_EXEC) != 0});
|
||||
char Tmp[PATH_MAX];
|
||||
auto PathLength = FEX::get_fdpath(file.fd, Tmp);
|
||||
if (PathLength != -1) {
|
||||
Sections.push_back({Base, (uintptr_t)rv, size, (off_t)off, fextl::string(Tmp, PathLength), (prot & PROT_EXEC) != 0});
|
||||
}
|
||||
|
||||
return true;
|
||||
@ -111,8 +111,7 @@ class ELFCodeLoader final : public FEXCore::CodeLoader {
|
||||
return rv;
|
||||
}
|
||||
|
||||
template <typename TMap, typename TUnmap>
|
||||
std::optional<uintptr_t> LoadElfFile(ELFParser& Elf, uintptr_t *BrkBase, TMap Mapper, TUnmap Unmapper, uint64_t LoadHint = 0) {
|
||||
std::optional<uintptr_t> LoadElfFile(ELFParser& Elf, uintptr_t *BrkBase, FEX::HLE::SyscallHandler *const Handler, uint64_t LoadHint = 0) {
|
||||
|
||||
uintptr_t LoadBase = 0;
|
||||
|
||||
@ -123,7 +122,7 @@ class ELFCodeLoader final : public FEXCore::CodeLoader {
|
||||
if (Elf.ehdr.e_type == ET_DYN) {
|
||||
// needs base address
|
||||
auto TotalSize = CalculateTotalElfSize(Elf.phdrs) + (BrkBase ? BRK_SIZE : 0);
|
||||
LoadBase = (uintptr_t)Mapper(reinterpret_cast<void*>(LoadHint), TotalSize, PROT_NONE, MAP_ANONYMOUS | MAP_PRIVATE, -1, 0);
|
||||
LoadBase = (uintptr_t)Handler->GuestMmap(reinterpret_cast<void*>(LoadHint), TotalSize, PROT_NONE, MAP_ANONYMOUS | MAP_PRIVATE, -1, 0);
|
||||
if ((void*)LoadBase == MAP_FAILED) {
|
||||
return {};
|
||||
}
|
||||
@ -141,7 +140,7 @@ class ELFCodeLoader final : public FEXCore::CodeLoader {
|
||||
int MapProt = MapFlags(Header);
|
||||
int MapType = MAP_PRIVATE | MAP_DENYWRITE | MAP_FIXED;
|
||||
|
||||
if (!MapFile(Elf, LoadBase, Header, MapProt, MapType, Mapper)) {
|
||||
if (!MapFile(Elf, LoadBase, Header, MapProt, MapType, Handler)) {
|
||||
return {};
|
||||
}
|
||||
|
||||
@ -157,7 +156,7 @@ class ELFCodeLoader final : public FEXCore::CodeLoader {
|
||||
}
|
||||
|
||||
if (BSSPageStart != BSSPageEnd) {
|
||||
auto bss = Mapper((void*)BSSPageStart, BSSPageEnd - BSSPageStart, MapProt, MapType | MAP_ANONYMOUS, -1, 0);
|
||||
auto bss = Handler->GuestMmap((void*)BSSPageStart, BSSPageEnd - BSSPageStart, MapProt, MapType | MAP_ANONYMOUS, -1, 0);
|
||||
if ((void*)bss == MAP_FAILED) {
|
||||
LogMan::Msg::EFmt("Failed to allocate BSS @ {}, {}\n", fmt::ptr(bss), errno);
|
||||
return {};
|
||||
@ -353,7 +352,7 @@ class ELFCodeLoader final : public FEXCore::CodeLoader {
|
||||
uint64_t val;
|
||||
};
|
||||
|
||||
bool MapMemory(const MapperFn& Mapper, const UnmapperFn& Unmapper) override {
|
||||
bool MapMemory(FEX::HLE::SyscallHandler *const Handler) {
|
||||
for (auto Header: MainElf.phdrs) {
|
||||
if (Header.p_type == PT_GNU_STACK) {
|
||||
if (Header.p_flags & PF_X)
|
||||
@ -407,7 +406,7 @@ class ELFCodeLoader final : public FEXCore::CodeLoader {
|
||||
uint64_t StackHint = Is64BitMode() ? STACK_HINT_64 : STACK_HINT_32;
|
||||
|
||||
// Allocate the base of the full 128MB stack range.
|
||||
StackPointerBase = Mapper(reinterpret_cast<void*>(StackHint), FULL_STACK_SIZE, PROT_NONE, MAP_PRIVATE | MAP_ANONYMOUS | MAP_STACK | MAP_GROWSDOWN | MAP_NORESERVE, -1, 0);
|
||||
StackPointerBase = Handler->GuestMmap(reinterpret_cast<void*>(StackHint), FULL_STACK_SIZE, PROT_NONE, MAP_PRIVATE | MAP_ANONYMOUS | MAP_STACK | MAP_GROWSDOWN | MAP_NORESERVE, -1, 0);
|
||||
|
||||
if (StackPointerBase == reinterpret_cast<void*>(~0ULL)) {
|
||||
LogMan::Msg::EFmt("Allocating stack failed");
|
||||
@ -415,7 +414,7 @@ class ELFCodeLoader final : public FEXCore::CodeLoader {
|
||||
}
|
||||
|
||||
// Allocate with permissions the 8MB of regular stack size.
|
||||
StackPointer = reinterpret_cast<uintptr_t>(Mapper(
|
||||
StackPointer = reinterpret_cast<uintptr_t>(Handler->GuestMmap(
|
||||
reinterpret_cast<void*>(reinterpret_cast<uint64_t>(StackPointerBase) + FULL_STACK_SIZE - StackSize()),
|
||||
StackSize(), PROT_READ | PROT_WRITE, MAP_FIXED | MAP_PRIVATE | MAP_ANONYMOUS | MAP_STACK | MAP_GROWSDOWN, -1, 0));
|
||||
|
||||
@ -464,7 +463,7 @@ class ELFCodeLoader final : public FEXCore::CodeLoader {
|
||||
|
||||
if (!MainElf.InterpreterElf.empty()) {
|
||||
uint64_t InterpLoadBase = 0;
|
||||
if (auto elf = LoadElfFile(InterpElf, nullptr, Mapper, Unmapper)) {
|
||||
if (auto elf = LoadElfFile(InterpElf, nullptr, Handler)) {
|
||||
InterpLoadBase = *elf;
|
||||
} else {
|
||||
LogMan::Msg::EFmt("Failed to load interpreter elf file");
|
||||
@ -530,7 +529,7 @@ class ELFCodeLoader final : public FEXCore::CodeLoader {
|
||||
|
||||
uintptr_t LoadBase = 0;
|
||||
|
||||
if (auto elf = LoadElfFile(MainElf, &BrkBase, Mapper, Unmapper, ELFLoadHint)) {
|
||||
if (auto elf = LoadElfFile(MainElf, &BrkBase, Handler, ELFLoadHint)) {
|
||||
LoadBase = *elf;
|
||||
if (MainElf.ehdr.e_type == ET_DYN) {
|
||||
BaseOffset = LoadBase;
|
||||
@ -542,7 +541,7 @@ class ELFCodeLoader final : public FEXCore::CodeLoader {
|
||||
|
||||
// XXX Randomise brk?
|
||||
|
||||
BrkStart = (uint64_t)Mapper((void*)BrkBase, BRK_SIZE, PROT_READ | PROT_WRITE, MAP_ANONYMOUS | MAP_PRIVATE | MAP_FIXED, -1, 0);
|
||||
BrkStart = (uint64_t)Handler->GuestMmap((void*)BrkBase, BRK_SIZE, PROT_READ | PROT_WRITE, MAP_ANONYMOUS | MAP_PRIVATE | MAP_FIXED, -1, 0);
|
||||
|
||||
if ((void*)BrkStart == MAP_FAILED) {
|
||||
LogMan::Msg::EFmt("Failed to allocate BRK @ {:x}, {}\n", BrkBase, errno);
|
||||
@ -585,7 +584,7 @@ class ELFCodeLoader final : public FEXCore::CodeLoader {
|
||||
if (!VSyscallEntry) [[unlikely]] {
|
||||
// If the VDSO thunk doesn't exist then we might not have a vsyscall entry.
|
||||
// Newer glibc requires vsyscall to exist now. So let's allocate a buffer and stick a vsyscall in to it.
|
||||
auto VSyscallPage = Mapper(nullptr, FHU::FEX_PAGE_SIZE, PROT_READ | PROT_WRITE, MAP_ANONYMOUS | MAP_PRIVATE, -1, 0);
|
||||
auto VSyscallPage = Handler->GuestMmap(nullptr, FHU::FEX_PAGE_SIZE, PROT_READ | PROT_WRITE, MAP_ANONYMOUS | MAP_PRIVATE, -1, 0);
|
||||
constexpr static uint8_t VSyscallCode[] = {
|
||||
0xcd, 0x80, // int 0x80
|
||||
0xc3, // ret
|
||||
|
@ -28,6 +28,7 @@ $end_info$
|
||||
#include <FEXCore/fextl/sstream.h>
|
||||
#include <FEXCore/fextl/string.h>
|
||||
#include <FEXCore/fextl/vector.h>
|
||||
#include <FEXHeaderUtils/Filesystem.h>
|
||||
|
||||
#include <atomic>
|
||||
#include <cerrno>
|
||||
@ -123,27 +124,31 @@ namespace FEXServerLogging {
|
||||
}
|
||||
|
||||
void InterpreterHandler(fextl::string *Filename, fextl::string const &RootFS, fextl::vector<fextl::string> *args) {
|
||||
// Open the file pointer to the filename and see if we need to find an interpreter
|
||||
std::fstream File(fextl::string_from_string(*Filename), std::fstream::in | std::fstream::binary);
|
||||
|
||||
if (!File.is_open()) {
|
||||
// Open the Filename to determine if it is a shebang file.
|
||||
int FD = open(Filename->c_str(), O_RDONLY | O_CLOEXEC);
|
||||
if (FD == -1) {
|
||||
return;
|
||||
}
|
||||
|
||||
File.seekg(0, std::fstream::end);
|
||||
const auto FileSize = File.tellg();
|
||||
File.seekg(0, std::fstream::beg);
|
||||
std::array<char, 257> Header;
|
||||
const auto ChunkSize = 257l;
|
||||
const auto ReadSize = pread(FD, &Header.at(0), ChunkSize, 0);
|
||||
|
||||
const auto Data = std::span<char>(Header.data(), ReadSize);
|
||||
|
||||
// Is the file large enough for shebang
|
||||
if (FileSize <= 2) {
|
||||
if (ReadSize <= 2) {
|
||||
close(FD);
|
||||
return;
|
||||
}
|
||||
|
||||
// Handle shebang files
|
||||
if (File.get() == '#' &&
|
||||
File.get() == '!') {
|
||||
fextl::string InterpreterLine;
|
||||
std::getline(File, InterpreterLine);
|
||||
if (Data[0] == '#' &&
|
||||
Data[1] == '!') {
|
||||
fextl::string InterpreterLine {
|
||||
Data.begin() + 2, // strip off "#!" prefix
|
||||
std::find(Data.begin(), Data.end(), '\n')
|
||||
};
|
||||
fextl::vector<fextl::string> ShebangArguments{};
|
||||
|
||||
// Shebang line can have a single argument
|
||||
@ -168,17 +173,14 @@ void InterpreterHandler(fextl::string *Filename, fextl::string const &RootFS, fe
|
||||
|
||||
// Insert all the arguments at the start
|
||||
args->insert(args->begin(), ShebangArguments.begin(), ShebangArguments.end());
|
||||
|
||||
// Done here
|
||||
return;
|
||||
}
|
||||
close(FD);
|
||||
}
|
||||
|
||||
void RootFSRedirect(fextl::string *Filename, fextl::string const &RootFS) {
|
||||
auto RootFSLink = ELFCodeLoader::ResolveRootfsFile(*Filename, RootFS);
|
||||
|
||||
std::error_code ec{};
|
||||
if (std::filesystem::exists(RootFSLink, ec)) {
|
||||
if (FHU::Filesystem::Exists(RootFSLink)) {
|
||||
*Filename = RootFSLink;
|
||||
}
|
||||
}
|
||||
@ -197,6 +199,7 @@ bool IsInterpreterInstalled() {
|
||||
}
|
||||
|
||||
int main(int argc, char **argv, char **const envp) {
|
||||
FEXCore::Allocator::GLIBCScopedFault GLIBFaultScope;
|
||||
const bool IsInterpreter = RanAsInterpreter(argv[0]);
|
||||
|
||||
ExecutedWithFD = getauxval(AT_EXECFD) != 0;
|
||||
@ -292,8 +295,7 @@ int main(int argc, char **argv, char **const envp) {
|
||||
RootFSRedirect(&Program.ProgramPath, LDPath());
|
||||
InterpreterHandler(&Program.ProgramPath, LDPath(), &Args);
|
||||
|
||||
std::error_code ec{};
|
||||
if (!ExecutedWithFD && !FEXFD && !std::filesystem::exists(Program.ProgramPath, ec)) {
|
||||
if (!ExecutedWithFD && !FEXFD && !FHU::Filesystem::Exists(Program.ProgramPath)) {
|
||||
// Early exit if the program passed in doesn't exist
|
||||
// Will prevent a crash later
|
||||
fmt::print(stderr, "{}: command not found\n", Program.ProgramPath);
|
||||
@ -342,12 +344,18 @@ int main(int argc, char **argv, char **const envp) {
|
||||
FEXCore::Config::EraseSet(FEXCore::Config::CONFIG_APP_CONFIG_NAME, "<Anonymous>");
|
||||
}
|
||||
else {
|
||||
FEXCore::Config::EraseSet(FEXCore::Config::CONFIG_APP_FILENAME, std::filesystem::canonical(Program.ProgramPath).string());
|
||||
{
|
||||
char ExistsTempPath[PATH_MAX];
|
||||
char *RealPath = realpath(Program.ProgramPath.c_str(), ExistsTempPath);
|
||||
if (RealPath) {
|
||||
FEXCore::Config::EraseSet(FEXCore::Config::CONFIG_APP_FILENAME, fextl::string(RealPath));
|
||||
}
|
||||
}
|
||||
FEXCore::Config::EraseSet(FEXCore::Config::CONFIG_APP_CONFIG_NAME, Program.ProgramName);
|
||||
}
|
||||
FEXCore::Config::EraseSet(FEXCore::Config::CONFIG_IS64BIT_MODE, Loader.Is64BitMode() ? "1" : "0");
|
||||
|
||||
std::unique_ptr<FEX::HLE::MemAllocator> Allocator;
|
||||
fextl::unique_ptr<FEX::HLE::MemAllocator> Allocator;
|
||||
fextl::vector<FEXCore::Allocator::MemoryRegion> Base48Bit;
|
||||
|
||||
if (Loader.Is64BitMode()) {
|
||||
@ -402,18 +410,17 @@ int main(int argc, char **argv, char **const envp) {
|
||||
auto SyscallHandler = Loader.Is64BitMode() ? FEX::HLE::x64::CreateHandler(CTX, SignalDelegation.get())
|
||||
: FEX::HLE::x32::CreateHandler(CTX, SignalDelegation.get(), std::move(Allocator));
|
||||
|
||||
auto Mapper = std::bind_front(&FEX::HLE::SyscallHandler::GuestMmap, SyscallHandler.get());
|
||||
auto Unmapper = std::bind_front(&FEX::HLE::SyscallHandler::GuestMunmap, SyscallHandler.get());
|
||||
{
|
||||
// Load VDSO in to memory prior to mapping our ELFs.
|
||||
void* VDSOBase = FEX::VDSO::LoadVDSOThunks(Loader.Is64BitMode(), SyscallHandler.get());
|
||||
Loader.SetVDSOBase(VDSOBase);
|
||||
Loader.CalculateHWCaps(CTX);
|
||||
|
||||
// Load VDSO in to memory prior to mapping our ELFs.
|
||||
void* VDSOBase = FEX::VDSO::LoadVDSOThunks(Loader.Is64BitMode(), Mapper);
|
||||
Loader.SetVDSOBase(VDSOBase);
|
||||
Loader.CalculateHWCaps(CTX);
|
||||
|
||||
if (!Loader.MapMemory(Mapper, Unmapper)) {
|
||||
// failed to map
|
||||
LogMan::Msg::EFmt("Failed to map %d-bit elf file.", Loader.Is64BitMode() ? 64 : 32);
|
||||
return -ENOEXEC;
|
||||
if (!Loader.MapMemory(SyscallHandler.get())) {
|
||||
// failed to map
|
||||
LogMan::Msg::EFmt("Failed to map %d-bit elf file.", Loader.Is64BitMode() ? 64 : 32);
|
||||
return -ENOEXEC;
|
||||
}
|
||||
}
|
||||
|
||||
SyscallHandler->SetCodeLoader(&Loader);
|
||||
@ -484,6 +491,7 @@ int main(int argc, char **argv, char **const envp) {
|
||||
}
|
||||
|
||||
if (AOTEnabled) {
|
||||
std::error_code ec{};
|
||||
std::filesystem::create_directories(std::filesystem::path(FEXCore::Config::GetDataDirectory()) / "aotir", ec);
|
||||
if (!ec) {
|
||||
CTX->WriteFilesWithCode([](const fextl::string& fileid, const fextl::string& filename) {
|
||||
@ -508,7 +516,6 @@ int main(int argc, char **argv, char **const envp) {
|
||||
SignalDelegation.reset();
|
||||
FEXCore::Context::Context::DestroyContext(CTX);
|
||||
|
||||
FEXCore::Context::ShutdownStaticTables();
|
||||
FEXCore::Threads::Shutdown();
|
||||
|
||||
Loader.FreeSections();
|
||||
@ -523,6 +530,7 @@ int main(int argc, char **argv, char **const envp) {
|
||||
// Allocator is now original system allocator
|
||||
FEXCore::Telemetry::Shutdown(Program.ProgramName);
|
||||
FEXCore::Profiler::Shutdown();
|
||||
|
||||
if (ShutdownReason == FEXCore::Context::ExitReason::EXIT_SHUTDOWN) {
|
||||
return ProgramStatus;
|
||||
}
|
||||
|
@ -1,6 +1,7 @@
|
||||
#pragma once
|
||||
|
||||
#include "Common/Config.h"
|
||||
#include "Tests/LinuxSyscalls/Syscalls.h"
|
||||
#include "Linux/Utils/ELFContainer.h"
|
||||
#include "Linux/Utils/ELFSymbolDatabase.h"
|
||||
|
||||
@ -21,6 +22,7 @@
|
||||
#include <FEXCore/Utils/CompilerDefs.h>
|
||||
#include <FEXCore/Utils/LogManager.h>
|
||||
#include <FEXCore/Utils/MathUtils.h>
|
||||
#include <FEXCore/fextl/fmt.h>
|
||||
#include <FEXCore/fextl/map.h>
|
||||
#include <FEXCore/fextl/string.h>
|
||||
#include <FEXCore/fextl/vector.h>
|
||||
@ -37,7 +39,7 @@ namespace FEX::HarnessHelper {
|
||||
bool SupportsAVX) {
|
||||
bool Matches = true;
|
||||
|
||||
const auto DumpGPRs = [OutputGPRs](const std::string& Name, uint64_t A, uint64_t B) {
|
||||
const auto DumpGPRs = [OutputGPRs](const fextl::string& Name, uint64_t A, uint64_t B) {
|
||||
if (!OutputGPRs) {
|
||||
return;
|
||||
}
|
||||
@ -48,7 +50,7 @@ namespace FEX::HarnessHelper {
|
||||
fmt::print("{}: 0x{:016x} {} 0x{:016x}\n", Name, A, A==B ? "==" : "!=", B);
|
||||
};
|
||||
|
||||
const auto DumpFLAGs = [OutputGPRs](const std::string& Name, uint64_t A, uint64_t B) {
|
||||
const auto DumpFLAGs = [OutputGPRs](const fextl::string& Name, uint64_t A, uint64_t B) {
|
||||
if (!OutputGPRs) {
|
||||
return;
|
||||
}
|
||||
@ -85,12 +87,12 @@ namespace FEX::HarnessHelper {
|
||||
}
|
||||
};
|
||||
|
||||
const auto CheckGPRs = [&Matches, DumpGPRs](const std::string& Name, uint64_t A, uint64_t B){
|
||||
const auto CheckGPRs = [&Matches, DumpGPRs](const fextl::string& Name, uint64_t A, uint64_t B){
|
||||
DumpGPRs(Name, A, B);
|
||||
Matches &= A == B;
|
||||
};
|
||||
|
||||
const auto CheckFLAGS = [&Matches, DumpFLAGs](const std::string& Name, uint64_t A, uint64_t B){
|
||||
const auto CheckFLAGS = [&Matches, DumpFLAGs](const fextl::string& Name, uint64_t A, uint64_t B){
|
||||
DumpFLAGs(Name, A, B);
|
||||
Matches &= A == B;
|
||||
};
|
||||
@ -106,7 +108,7 @@ namespace FEX::HarnessHelper {
|
||||
// GPRS
|
||||
for (unsigned i = 0; i < FEXCore::Core::CPUState::NUM_GPRS; ++i, MatchMask >>= 1) {
|
||||
if (MatchMask & 1) {
|
||||
CheckGPRs("GPR" + std::to_string(i), State1.gregs[i], State2.gregs[i]);
|
||||
CheckGPRs(fextl::fmt::format("GPR{}", std::to_string(i)), State1.gregs[i], State2.gregs[i]);
|
||||
}
|
||||
}
|
||||
|
||||
@ -114,15 +116,15 @@ namespace FEX::HarnessHelper {
|
||||
if (SupportsAVX) {
|
||||
for (size_t i = 0; i < FEXCore::Core::CPUState::NUM_XMMS; ++i, MatchMask >>= 1) {
|
||||
if (MatchMask & 1) {
|
||||
CheckGPRs("XMM0_" + std::to_string(i), State1.xmm.avx.data[i][0], State2.xmm.avx.data[i][0]);
|
||||
CheckGPRs("XMM1_" + std::to_string(i), State1.xmm.avx.data[i][1], State2.xmm.avx.data[i][1]);
|
||||
CheckGPRs(fextl::fmt::format("XMM0_{}", std::to_string(i)), State1.xmm.avx.data[i][0], State2.xmm.avx.data[i][0]);
|
||||
CheckGPRs(fextl::fmt::format("XMM1_{}", std::to_string(i)), State1.xmm.avx.data[i][1], State2.xmm.avx.data[i][1]);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
for (size_t i = 0; i < FEXCore::Core::CPUState::NUM_XMMS; ++i, MatchMask >>= 1) {
|
||||
if (MatchMask & 1) {
|
||||
CheckGPRs("XMM0_" + std::to_string(i), State1.xmm.sse.data[i][0], State2.xmm.sse.data[i][0]);
|
||||
CheckGPRs("XMM1_" + std::to_string(i), State1.xmm.sse.data[i][1], State2.xmm.sse.data[i][1]);
|
||||
CheckGPRs(fextl::fmt::format("XMM0_{}", std::to_string(i)), State1.xmm.sse.data[i][0], State2.xmm.sse.data[i][0]);
|
||||
CheckGPRs(fextl::fmt::format("XMM1_{}", std::to_string(i)), State1.xmm.sse.data[i][1], State2.xmm.sse.data[i][1]);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -159,16 +161,29 @@ namespace FEX::HarnessHelper {
|
||||
}
|
||||
|
||||
inline void ReadFile(fextl::string const &Filename, fextl::vector<char> *Data) {
|
||||
std::fstream TestFile(fextl::string_from_string(Filename), std::fstream::in | std::fstream::binary);
|
||||
LOGMAN_THROW_A_FMT(TestFile.is_open(), "Failed to open file");
|
||||
int fd = open(Filename.c_str(), O_RDONLY | O_CLOEXEC);
|
||||
if (fd == -1) {
|
||||
LogMan::Msg::AFmt("Failed to open file");
|
||||
}
|
||||
|
||||
TestFile.seekg(0, std::fstream::end);
|
||||
const size_t FileSize = TestFile.tellg();
|
||||
TestFile.seekg(0, std::fstream::beg);
|
||||
struct stat buf;
|
||||
if (fstat(fd, &buf) != 0) {
|
||||
close(fd);
|
||||
LogMan::Msg::AFmt("Failed to open file");
|
||||
}
|
||||
|
||||
auto FileSize = buf.st_size;
|
||||
|
||||
if (FileSize <= 0) {
|
||||
close(fd);
|
||||
LogMan::Msg::AFmt("Failed to open file");
|
||||
}
|
||||
|
||||
Data->resize(FileSize);
|
||||
const auto ReadSize = pread(fd, Data->data(), FileSize, 0);
|
||||
|
||||
TestFile.read(Data->data(), FileSize);
|
||||
close(fd);
|
||||
LOGMAN_THROW_AA_FMT(ReadSize == FileSize, "Failed to open file");
|
||||
}
|
||||
|
||||
class ConfigLoader final {
|
||||
@ -307,15 +322,15 @@ namespace FEX::HarnessHelper {
|
||||
uint64_t *State1Data = reinterpret_cast<uint64_t*>(reinterpret_cast<uint64_t>(State1) + Offset);
|
||||
uint64_t *State2Data = reinterpret_cast<uint64_t*>(reinterpret_cast<uint64_t>(State2) + Offset);
|
||||
|
||||
const auto DumpGPRs = [this](const std::string& Name, uint64_t A, uint64_t B) {
|
||||
const auto DumpGPRs = [this](const fextl::string& Name, uint64_t A, uint64_t B) {
|
||||
if (!ConfigDumpGPRs()) {
|
||||
return;
|
||||
}
|
||||
|
||||
fmt::print("{}: 0x{:016x} {} 0x{:016x} (Expected)\n", Name, A, A==B ? "==" : "!=", B);
|
||||
fextl::fmt::print("{}: 0x{:016x} {} 0x{:016x} (Expected)\n", Name, A, A==B ? "==" : "!=", B);
|
||||
};
|
||||
|
||||
const auto CheckGPRs = [&Matches, DumpGPRs](const std::string& Name, uint64_t A, uint64_t B) {
|
||||
const auto CheckGPRs = [&Matches, DumpGPRs](const fextl::string& Name, uint64_t A, uint64_t B) {
|
||||
DumpGPRs(Name, A, B);
|
||||
Matches &= A == B;
|
||||
};
|
||||
@ -325,9 +340,9 @@ namespace FEX::HarnessHelper {
|
||||
if (NameIndex == 0) // RIP
|
||||
Name = "RIP";
|
||||
else if (NameIndex >= 1 && NameIndex < 17)
|
||||
Name = fmt::format("GPR{}", NameIndex - 1);
|
||||
Name = fextl::fmt::format("GPR{}", NameIndex - 1);
|
||||
else if (NameIndex >= 17 && NameIndex < 33)
|
||||
Name = fmt::format("XMM[{}][{}]", NameIndex - 17, j);
|
||||
Name = fextl::fmt::format("XMM[{}][{}]", NameIndex - 17, j);
|
||||
else if (NameIndex == 33)
|
||||
Name = "gs";
|
||||
else if (NameIndex == 34)
|
||||
@ -335,13 +350,13 @@ namespace FEX::HarnessHelper {
|
||||
else if (NameIndex == 35)
|
||||
Name = "rflags";
|
||||
else if (NameIndex >= 36 && NameIndex < 45)
|
||||
Name = fmt::format("MM[{}][{}]", NameIndex - 36, j);
|
||||
Name = fextl::fmt::format("MM[{}][{}]", NameIndex - 36, j);
|
||||
|
||||
if (State1) {
|
||||
CheckGPRs(fmt::format("Core1: {}: ", Name), State1Data[j], RegData->RegValues[j]);
|
||||
CheckGPRs(fextl::fmt::format("Core1: {}: ", Name), State1Data[j], RegData->RegValues[j]);
|
||||
}
|
||||
if (State2) {
|
||||
CheckGPRs(fmt::format("Core2: {}: ", Name), State2Data[j], RegData->RegValues[j]);
|
||||
CheckGPRs(fextl::fmt::format("Core2: {}: ", Name), State2Data[j], RegData->RegValues[j]);
|
||||
}
|
||||
}
|
||||
|
||||
@ -475,39 +490,39 @@ namespace FEX::HarnessHelper {
|
||||
return RIP;
|
||||
}
|
||||
|
||||
bool MapMemory(const MapperFn& Mapper, const UnmapperFn& Unmapper) override {
|
||||
bool MapMemoryInternal(auto Mapper, auto Munmap) {
|
||||
bool LimitedSize = true;
|
||||
auto DoMMap = [&Mapper](uint64_t Address, size_t Size) -> void* {
|
||||
void *Result = Mapper(reinterpret_cast<void*>(Address), Size, PROT_READ | PROT_WRITE | PROT_EXEC, MAP_FIXED | MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
|
||||
auto DoMMap = [](auto This, auto Mapper, uint64_t Address, size_t Size) -> void* {
|
||||
void *Result = (This->*Mapper)(reinterpret_cast<void*>(Address), Size, PROT_READ | PROT_WRITE | PROT_EXEC, MAP_FIXED | MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
|
||||
LOGMAN_THROW_AA_FMT(Result == reinterpret_cast<void*>(Address), "Map Memory mmap failed");
|
||||
return Result;
|
||||
};
|
||||
|
||||
if (LimitedSize) {
|
||||
DoMMap(0xe000'0000, FHU::FEX_PAGE_SIZE * 10);
|
||||
DoMMap(this, Mapper, 0xe000'0000, FHU::FEX_PAGE_SIZE * 10);
|
||||
|
||||
// SIB8
|
||||
// We test [-128, -126] (Bottom)
|
||||
// We test [-8, 8] (Middle)
|
||||
// We test [120, 127] (Top)
|
||||
// Can fit in two pages
|
||||
DoMMap(0xe800'0000 - FHU::FEX_PAGE_SIZE, FHU::FEX_PAGE_SIZE * 2);
|
||||
DoMMap(this, Mapper, 0xe800'0000 - FHU::FEX_PAGE_SIZE, FHU::FEX_PAGE_SIZE * 2);
|
||||
}
|
||||
else {
|
||||
// This is scratch memory location and SIB8 location
|
||||
DoMMap(0xe000'0000, 0x1000'0000);
|
||||
DoMMap(this, Mapper, 0xe000'0000, 0x1000'0000);
|
||||
// This is for large SIB 32bit displacement testing
|
||||
DoMMap(0x2'0000'0000, 0x1'0000'1000);
|
||||
DoMMap(this, Mapper, 0x2'0000'0000, 0x1'0000'1000);
|
||||
}
|
||||
|
||||
// Map in the memory region for the test file
|
||||
size_t Length = FEXCore::AlignUp(TestFileSize, FHU::FEX_PAGE_SIZE);
|
||||
Mapper(reinterpret_cast<void*>(Code_start_page), Length, PROT_READ | PROT_WRITE | PROT_EXEC, MAP_FIXED | MAP_PRIVATE, TestFD, 0);
|
||||
(this->*Mapper)(reinterpret_cast<void*>(Code_start_page), Length, PROT_READ | PROT_WRITE | PROT_EXEC, MAP_FIXED | MAP_PRIVATE, TestFD, 0);
|
||||
RIP = Code_start_page;
|
||||
|
||||
// Map the memory regions the test file asks for
|
||||
for (auto& [region, size] : Config.GetMemoryRegions()) {
|
||||
DoMMap(region, size);
|
||||
DoMMap(this, Mapper, region, size);
|
||||
}
|
||||
|
||||
LoadMemory();
|
||||
@ -515,6 +530,15 @@ namespace FEX::HarnessHelper {
|
||||
return true;
|
||||
}
|
||||
|
||||
bool MapMemory(FEX::HLE::SyscallHandler *const Handler) {
|
||||
SyscallHandler = Handler;
|
||||
return MapMemoryInternal(&FEX::HarnessHelper::HarnessCodeLoader::SyscallMMap, &FEX::HarnessHelper::HarnessCodeLoader::SyscallMunmap);
|
||||
}
|
||||
|
||||
bool MapMemory() {
|
||||
return MapMemoryInternal(&FEX::HarnessHelper::HarnessCodeLoader::MMap, &FEX::HarnessHelper::HarnessCodeLoader::Munmap);
|
||||
}
|
||||
|
||||
void LoadMemory() {
|
||||
// Memory base here starts at the start location we passed back with GetLayout()
|
||||
// This will write at [CODE_START_RANGE + 0, RawFile.size() )
|
||||
@ -540,7 +564,23 @@ namespace FEX::HarnessHelper {
|
||||
bool RequiresBMI2() const { return Config.RequiresBMI2(); }
|
||||
bool RequiresCLWB() const { return Config.RequiresCLWB(); }
|
||||
|
||||
protected:
|
||||
void *SyscallMMap(void *addr, size_t length, int prot, int flags, int fd, off_t offset) {
|
||||
return SyscallHandler->GuestMmap(addr, length, prot, flags, fd, offset);
|
||||
}
|
||||
int SyscallMunmap(void *addr, size_t length) {
|
||||
return SyscallHandler->GuestMunmap(addr, length);
|
||||
}
|
||||
|
||||
void *MMap(void *addr, size_t length, int prot, int flags, int fd, off_t offset) {
|
||||
return mmap(addr, length, prot, flags, fd, offset);
|
||||
}
|
||||
int Munmap(void *addr, size_t length) {
|
||||
return munmap(addr, length);
|
||||
}
|
||||
private:
|
||||
FEX::HLE::SyscallHandler *SyscallHandler{};
|
||||
|
||||
constexpr static uint64_t STACK_SIZE = FHU::FEX_PAGE_SIZE;
|
||||
constexpr static uint64_t STACK_OFFSET = 0xc000'0000;
|
||||
// Zero is special case to know when we are done
|
||||
|
@ -172,7 +172,7 @@ int main(int argc, char **argv, char **const envp)
|
||||
LogMan::Msg::InstallHandler(MsgHandler);
|
||||
|
||||
FEXCore::Config::Initialize();
|
||||
FEXCore::Config::AddLayer(std::make_unique<FEX::ArgLoader::ArgLoader>(argc, argv));
|
||||
FEXCore::Config::AddLayer(fextl::make_unique<FEX::ArgLoader::ArgLoader>(argc, argv));
|
||||
FEXCore::Config::AddLayer(FEXCore::Config::CreateEnvironmentLayer(envp));
|
||||
FEXCore::Config::Load();
|
||||
// Ensure the IRLoader runs in 64-bit mode.
|
||||
|
@ -17,6 +17,7 @@ $end_info$
|
||||
#include <FEXCore/fextl/fmt.h>
|
||||
#include <FEXCore/fextl/string.h>
|
||||
#include <FEXCore/fextl/sstream.h>
|
||||
#include <FEXHeaderUtils/Filesystem.h>
|
||||
|
||||
#include <git_version.h>
|
||||
|
||||
@ -759,12 +760,12 @@ namespace FEX::EmulatedFile {
|
||||
char *RealPath = realpath(Path, ExistsTempPath);
|
||||
if (RealPath) {
|
||||
RealPathExists = true;
|
||||
Creator = FDReadCreators.find(realpath(Path, Tmp));
|
||||
Creator = FDReadCreators.find(RealPath);
|
||||
}
|
||||
}
|
||||
|
||||
if (!RealPathExists) {
|
||||
Creator = FDReadCreators.find(fextl::string_from_path(std::filesystem::path(Path).lexically_normal()));
|
||||
Creator = FDReadCreators.find(FHU::Filesystem::LexicallyNormal(Path));
|
||||
}
|
||||
|
||||
if (Creator == FDReadCreators.end()) {
|
||||
|
@ -19,6 +19,7 @@ $end_info$
|
||||
#include <FEXCore/fextl/list.h>
|
||||
#include <FEXCore/fextl/string.h>
|
||||
#include <FEXCore/fextl/vector.h>
|
||||
#include <FEXHeaderUtils/Filesystem.h>
|
||||
#include <FEXHeaderUtils/ScopedSignalMask.h>
|
||||
#include <FEXHeaderUtils/Syscalls.h>
|
||||
|
||||
@ -42,13 +43,13 @@ $end_info$
|
||||
namespace JSON {
|
||||
struct JsonAllocator {
|
||||
jsonPool_t PoolObject;
|
||||
std::unique_ptr<fextl::list<json_t>> json_objects;
|
||||
fextl::unique_ptr<fextl::list<json_t>> json_objects;
|
||||
};
|
||||
static_assert(offsetof(JsonAllocator, PoolObject) == 0, "This needs to be at offset zero");
|
||||
|
||||
json_t* PoolInit(jsonPool_t* Pool) {
|
||||
JsonAllocator* alloc = reinterpret_cast<JsonAllocator*>(Pool);
|
||||
alloc->json_objects = std::make_unique<fextl::list<json_t>>();
|
||||
alloc->json_objects = fextl::make_unique<fextl::list<json_t>>();
|
||||
return &*alloc->json_objects->emplace(alloc->json_objects->end());
|
||||
}
|
||||
|
||||
@ -62,39 +63,31 @@ namespace FEX::HLE {
|
||||
struct open_how;
|
||||
|
||||
static bool LoadFile(fextl::vector<char> &Data, const fextl::string &Filename) {
|
||||
std::fstream File(fextl::string_from_string(Filename), std::ios::in);
|
||||
|
||||
if (!File.is_open()) {
|
||||
int fd = open(Filename.c_str(), O_RDONLY | O_CLOEXEC);
|
||||
if (fd == -1) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!File.seekg(0, std::fstream::end)) {
|
||||
LogMan::Msg::DFmt("Couldn't load configuration file: Seek end");
|
||||
struct stat buf;
|
||||
if (fstat(fd, &buf) != 0) {
|
||||
LogMan::Msg::DFmt("Couldn't load configuration file: fstat");
|
||||
close(fd);
|
||||
return false;
|
||||
}
|
||||
|
||||
auto FileSize = File.tellg();
|
||||
if (File.fail()) {
|
||||
LogMan::Msg::DFmt("Couldn't load configuration file: tellg");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!File.seekg(0, std::fstream::beg)) {
|
||||
LogMan::Msg::DFmt("Couldn't load configuration file: Seek beginning");
|
||||
return false;
|
||||
}
|
||||
auto FileSize = buf.st_size;
|
||||
|
||||
if (FileSize <= 0) {
|
||||
LogMan::Msg::DFmt("FileSize less than or equal to zero specified");
|
||||
close(fd);
|
||||
return false;
|
||||
}
|
||||
|
||||
Data.resize(FileSize);
|
||||
if (!File.read(Data.data(), FileSize)) {
|
||||
// Probably means permissions aren't set. Just early exit
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
const auto ReadSize = pread(fd, Data.data(), FileSize, 0);
|
||||
|
||||
close(fd);
|
||||
return ReadSize == FileSize;
|
||||
}
|
||||
|
||||
struct ThunkDBObject {
|
||||
@ -216,7 +209,6 @@ static void LoadThunkDatabase(fextl::unordered_map<fextl::string, ThunkDBObject>
|
||||
|
||||
FileManager::FileManager(FEXCore::Context::Context *ctx)
|
||||
: EmuFD {ctx} {
|
||||
|
||||
auto ThunkConfigFile = ThunkConfig();
|
||||
|
||||
// We try to load ThunksDB from:
|
||||
@ -287,7 +279,7 @@ FileManager::FileManager(FEXCore::Context::Context *ctx)
|
||||
}
|
||||
|
||||
// Now that we loaded the thunks object, walk through and ensure dependencies are enabled as well
|
||||
auto ThunkGuestPath = std::filesystem::path { Is64BitMode() ? ThunkGuestLibs() : ThunkGuestLibs32() };
|
||||
auto ThunkGuestPath = Is64BitMode() ? ThunkGuestLibs() : ThunkGuestLibs32() ;
|
||||
for (auto const &DBObject : ThunkDB) {
|
||||
if (!DBObject.second.Enabled) {
|
||||
continue;
|
||||
@ -298,17 +290,17 @@ FileManager::FileManager(FEXCore::Context::Context *ctx)
|
||||
struct {
|
||||
decltype(FileManager::ThunkOverlays)& ThunkOverlays;
|
||||
decltype(ThunkDB)& ThunkDB;
|
||||
const std::filesystem::path& ThunkGuestPath;
|
||||
const fextl::string& ThunkGuestPath;
|
||||
bool Is64BitMode;
|
||||
|
||||
void SetupOverlay(const ThunkDBObject& DBDepend) {
|
||||
auto ThunkPath = ThunkGuestPath / DBDepend.LibraryName;
|
||||
if (!std::filesystem::exists(ThunkPath)) {
|
||||
auto ThunkPath = fextl::fmt::format("{}/{}", ThunkGuestPath, DBDepend.LibraryName);
|
||||
if (!FHU::Filesystem::Exists(ThunkPath)) {
|
||||
if (!Is64BitMode) {
|
||||
// Guest libraries not existing is expected since not all libraries are thunked on 32-bit
|
||||
return;
|
||||
}
|
||||
ERROR_AND_DIE_FMT("Requested thunking via guest library \"{}\" that does not exist", ThunkPath.string());
|
||||
ERROR_AND_DIE_FMT("Requested thunking via guest library \"{}\" that does not exist", ThunkPath);
|
||||
}
|
||||
|
||||
for (const auto& Overlay : DBDepend.Overlays) {
|
||||
@ -663,7 +655,11 @@ uint64_t FileManager::Readlinkat(int dirfd, const char *pathname, char *buf, siz
|
||||
dirfd != AT_FDCWD) {
|
||||
// Passed in a dirfd that isn't magic FDCWD
|
||||
// We need to get the path from the fd now
|
||||
Path = FEX::get_fdpath(dirfd).value_or("");
|
||||
char Tmp[PATH_MAX] = "";
|
||||
auto PathLength = FEX::get_fdpath(dirfd, Tmp);
|
||||
if (PathLength != -1) {
|
||||
Path = fextl::string(Tmp, PathLength);
|
||||
}
|
||||
|
||||
if (pathname) {
|
||||
if (!Path.empty()) {
|
||||
|
@ -5,6 +5,7 @@
|
||||
#include <FEXHeaderUtils/Syscalls.h>
|
||||
#include <FEXHeaderUtils/TypeDefines.h>
|
||||
#include <FEXCore/fextl/map.h>
|
||||
#include <FEXCore/fextl/memory.h>
|
||||
|
||||
#include <bitset>
|
||||
#include <linux/mman.h>
|
||||
@ -44,6 +45,7 @@ public:
|
||||
FindPageRangePtr = &MemAllocator32Bit::FindPageRange;
|
||||
}
|
||||
}
|
||||
|
||||
void *Mmap(void *addr, size_t length, int prot, int flags, int fd, off_t offset) override;
|
||||
int Munmap(void *addr, size_t length) override;
|
||||
void *Mremap(void *old_address, size_t old_size, size_t new_size, int flags, void *new_address) override;
|
||||
@ -603,12 +605,12 @@ public:
|
||||
}
|
||||
};
|
||||
|
||||
std::unique_ptr<FEX::HLE::MemAllocator> Create32BitAllocator() {
|
||||
return std::make_unique<MemAllocator32Bit>();
|
||||
fextl::unique_ptr<FEX::HLE::MemAllocator> Create32BitAllocator() {
|
||||
return fextl::make_unique<MemAllocator32Bit>();
|
||||
}
|
||||
|
||||
std::unique_ptr<FEX::HLE::MemAllocator> CreatePassthroughAllocator() {
|
||||
return std::make_unique<MemAllocatorPassThrough>();
|
||||
fextl::unique_ptr<FEX::HLE::MemAllocator> CreatePassthroughAllocator() {
|
||||
return fextl::make_unique<MemAllocatorPassThrough>();
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -1,5 +1,7 @@
|
||||
#pragma once
|
||||
|
||||
#include <FEXCore/fextl/memory.h>
|
||||
|
||||
#include <cstdint>
|
||||
#include <memory>
|
||||
|
||||
@ -16,6 +18,6 @@ namespace FEX::HLE {
|
||||
virtual uint64_t Shmdt(const void* shmaddr) = 0;
|
||||
};
|
||||
|
||||
std::unique_ptr<FEX::HLE::MemAllocator> Create32BitAllocator();
|
||||
std::unique_ptr<FEX::HLE::MemAllocator> CreatePassthroughAllocator();
|
||||
fextl::unique_ptr<FEX::HLE::MemAllocator> Create32BitAllocator();
|
||||
fextl::unique_ptr<FEX::HLE::MemAllocator> CreatePassthroughAllocator();
|
||||
}
|
||||
|
@ -23,7 +23,7 @@ namespace Core {
|
||||
}
|
||||
|
||||
namespace FEX::HLE {
|
||||
class SignalDelegator final : public FEXCore::SignalDelegator {
|
||||
class SignalDelegator final : public FEXCore::SignalDelegator, public FEXCore::Allocator::FEXAllocOperators {
|
||||
public:
|
||||
// Returns true if the host handled the signal
|
||||
// Arguments are the same as sigaction handler
|
||||
|
@ -6,6 +6,7 @@ desc: Glue logic, brk allocations
|
||||
$end_info$
|
||||
*/
|
||||
|
||||
#include "FEXHeaderUtils/Filesystem.h"
|
||||
#include "Linux/Utils/ELFContainer.h"
|
||||
#include "Linux/Utils/ELFParser.h"
|
||||
|
||||
@ -237,7 +238,6 @@ static bool IsShebangFilename(fextl::string const &Filename) {
|
||||
uint64_t ExecveHandler(const char *pathname, char* const* argv, char* const* envp, ExecveAtArgs Args) {
|
||||
fextl::string Filename{};
|
||||
|
||||
std::error_code ec;
|
||||
fextl::string RootFS = FEX::HLE::_SyscallHandler->RootFSPath();
|
||||
ELFLoader::ELFContainer::ELFType Type{};
|
||||
|
||||
@ -257,7 +257,7 @@ uint64_t ExecveHandler(const char *pathname, char* const* argv, char* const* env
|
||||
// For absolute paths, check the rootfs first (if available)
|
||||
if (pathname[0] == '/') {
|
||||
auto Path = FEX::HLE::_SyscallHandler->FM.GetEmulatedPath(pathname, true);
|
||||
if (!Path.empty() && std::filesystem::exists(Path, ec)) {
|
||||
if (!Path.empty() && FHU::Filesystem::Exists(Path)) {
|
||||
Filename = Path;
|
||||
}
|
||||
else {
|
||||
@ -268,8 +268,8 @@ uint64_t ExecveHandler(const char *pathname, char* const* argv, char* const* env
|
||||
Filename = pathname;
|
||||
}
|
||||
|
||||
bool exists = std::filesystem::exists(Filename, ec);
|
||||
if (ec || !exists) {
|
||||
bool exists = FHU::Filesystem::Exists(Filename);
|
||||
if (!exists) {
|
||||
return -ENOENT;
|
||||
}
|
||||
|
||||
@ -867,7 +867,7 @@ static bool isHEX(char c) {
|
||||
return (c >= '0' && c <= '9') || (c >= 'a' && c <= 'f');
|
||||
}
|
||||
|
||||
std::unique_ptr<FEXCore::HLE::SourcecodeMap> SyscallHandler::GenerateMap(const std::string_view& GuestBinaryFile, const std::string_view& GuestBinaryFileId) {
|
||||
fextl::unique_ptr<FEXCore::HLE::SourcecodeMap> SyscallHandler::GenerateMap(const std::string_view& GuestBinaryFile, const std::string_view& GuestBinaryFileId) {
|
||||
|
||||
ELFParser GuestELF;
|
||||
|
||||
@ -929,7 +929,7 @@ std::unique_ptr<FEXCore::HLE::SourcecodeMap> SyscallHandler::GenerateMap(const s
|
||||
goto DoGenerate;
|
||||
}
|
||||
|
||||
auto rv = std::make_unique<FEXCore::HLE::SourcecodeMap>();
|
||||
auto rv = fextl::make_unique<FEXCore::HLE::SourcecodeMap>();
|
||||
|
||||
{
|
||||
auto len = rv->SourceFile.size();
|
||||
@ -1006,7 +1006,7 @@ std::unique_ptr<FEXCore::HLE::SourcecodeMap> SyscallHandler::GenerateMap(const s
|
||||
uintptr_t CurrentOffset{};
|
||||
int LastOffsetLine;
|
||||
|
||||
auto rv = std::make_unique<FEXCore::HLE::SourcecodeMap>();
|
||||
auto rv = fextl::make_unique<FEXCore::HLE::SourcecodeMap>();
|
||||
|
||||
rv->SourceFile = GuestSourceFile;
|
||||
|
||||
|
@ -16,6 +16,7 @@ $end_info$
|
||||
#include <FEXCore/IR/IR.h>
|
||||
#include <FEXCore/Utils/CompilerDefs.h>
|
||||
#include <FEXCore/fextl/map.h>
|
||||
#include <FEXCore/fextl/memory.h>
|
||||
#include <FEXCore/fextl/string.h>
|
||||
#include <FEXCore/fextl/vector.h>
|
||||
|
||||
@ -92,7 +93,7 @@ struct ExecveAtArgs {
|
||||
|
||||
uint64_t ExecveHandler(const char *pathname, char* const* argv, char* const* envp, ExecveAtArgs Args);
|
||||
|
||||
class SyscallHandler : public FEXCore::HLE::SyscallHandler, FEXCore::HLE::SourcecodeResolver {
|
||||
class SyscallHandler : public FEXCore::HLE::SyscallHandler, FEXCore::HLE::SourcecodeResolver, public FEXCore::Allocator::FEXAllocOperators {
|
||||
public:
|
||||
virtual ~SyscallHandler();
|
||||
|
||||
@ -252,9 +253,9 @@ private:
|
||||
void Strace(FEXCore::HLE::SyscallArguments *Args, uint64_t Ret);
|
||||
#endif
|
||||
|
||||
std::unique_ptr<FEX::HLE::MemAllocator> Alloc32Handler{};
|
||||
fextl::unique_ptr<FEX::HLE::MemAllocator> Alloc32Handler{};
|
||||
|
||||
std::unique_ptr<FEXCore::HLE::SourcecodeMap> GenerateMap(const std::string_view& GuestBinaryFile, const std::string_view& GuestBinaryFileId) override;
|
||||
fextl::unique_ptr<FEXCore::HLE::SourcecodeMap> GenerateMap(const std::string_view& GuestBinaryFile, const std::string_view& GuestBinaryFileId) override;
|
||||
|
||||
///// VMA (Virtual Memory Area) tracking /////
|
||||
|
||||
|
@ -199,14 +199,16 @@ void SyscallHandler::TrackMmap(uintptr_t Base, uintptr_t Size, int Prot, int Fla
|
||||
fstat64(fd, &buf);
|
||||
MRID mrid {buf.st_dev, buf.st_ino};
|
||||
|
||||
auto filename = FEX::get_fdpath(fd);
|
||||
char Tmp[PATH_MAX];
|
||||
auto PathLength = FEX::get_fdpath(fd, Tmp);
|
||||
|
||||
if (filename.has_value()) {
|
||||
if (PathLength != -1) {
|
||||
Tmp[PathLength] = '\0';
|
||||
auto [Iter, Inserted] = VMATracking.MappedResources.emplace(mrid, MappedResource {nullptr, nullptr, 0});
|
||||
Resource = &Iter->second;
|
||||
|
||||
if (Inserted) {
|
||||
Resource->AOTIRCacheEntry = CTX->LoadAOTIRCacheEntry(filename.value());
|
||||
Resource->AOTIRCacheEntry = CTX->LoadAOTIRCacheEntry(fextl::string(Tmp, PathLength));
|
||||
Resource->Iterator = Iter;
|
||||
}
|
||||
}
|
||||
|
@ -11,6 +11,7 @@ $end_info$
|
||||
|
||||
#include <FEXCore/HLE/SyscallHandler.h>
|
||||
#include <FEXCore/Utils/LogManager.h>
|
||||
#include <FEXCore/fextl/memory.h>
|
||||
|
||||
#include <bitset>
|
||||
#include <cerrno>
|
||||
@ -39,7 +40,7 @@ namespace FEX::HLE::x32 {
|
||||
void RegisterTime(FEX::HLE::SyscallHandler *Handler);
|
||||
void RegisterTimer(FEX::HLE::SyscallHandler *Handler);
|
||||
|
||||
x32SyscallHandler::x32SyscallHandler(FEXCore::Context::Context *ctx, FEX::HLE::SignalDelegator *_SignalDelegation, std::unique_ptr<MemAllocator> Allocator)
|
||||
x32SyscallHandler::x32SyscallHandler(FEXCore::Context::Context *ctx, FEX::HLE::SignalDelegator *_SignalDelegation, fextl::unique_ptr<MemAllocator> Allocator)
|
||||
: SyscallHandler{ctx, _SignalDelegation}, AllocHandler{std::move(Allocator)} {
|
||||
OSABI = FEXCore::HLE::SyscallOSABI::OS_LINUX32;
|
||||
RegisterSyscallHandlers();
|
||||
@ -110,8 +111,8 @@ namespace FEX::HLE::x32 {
|
||||
#endif
|
||||
}
|
||||
|
||||
std::unique_ptr<FEX::HLE::SyscallHandler> CreateHandler(FEXCore::Context::Context *ctx, FEX::HLE::SignalDelegator *_SignalDelegation, std::unique_ptr<MemAllocator> Allocator) {
|
||||
return std::make_unique<x32SyscallHandler>(ctx, _SignalDelegation, std::move(Allocator));
|
||||
fextl::unique_ptr<FEX::HLE::SyscallHandler> CreateHandler(FEXCore::Context::Context *ctx, FEX::HLE::SignalDelegator *_SignalDelegation, fextl::unique_ptr<MemAllocator> Allocator) {
|
||||
return fextl::make_unique<x32SyscallHandler>(ctx, _SignalDelegation, std::move(Allocator));
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -6,6 +6,7 @@ $end_info$
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <FEXCore/fextl/memory.h>
|
||||
#include <FEXCore/fextl/string.h>
|
||||
|
||||
#include "Tests/LinuxSyscalls/Syscalls.h"
|
||||
@ -33,7 +34,7 @@ namespace FEX::HLE::x32 {
|
||||
|
||||
class x32SyscallHandler final : public FEX::HLE::SyscallHandler {
|
||||
public:
|
||||
x32SyscallHandler(FEXCore::Context::Context *ctx, FEX::HLE::SignalDelegator *_SignalDelegation, std::unique_ptr<MemAllocator> Allocator);
|
||||
x32SyscallHandler(FEXCore::Context::Context *ctx, FEX::HLE::SignalDelegator *_SignalDelegation, fextl::unique_ptr<MemAllocator> Allocator);
|
||||
|
||||
FEX::HLE::MemAllocator *GetAllocator() { return AllocHandler.get(); }
|
||||
void *GuestMmap(void *addr, size_t length, int prot, int flags, int fd, off_t offset) override;
|
||||
@ -69,12 +70,12 @@ public:
|
||||
|
||||
private:
|
||||
void RegisterSyscallHandlers();
|
||||
std::unique_ptr<MemAllocator> AllocHandler{};
|
||||
fextl::unique_ptr<MemAllocator> AllocHandler{};
|
||||
};
|
||||
|
||||
std::unique_ptr<FEX::HLE::SyscallHandler> CreateHandler(FEXCore::Context::Context *ctx,
|
||||
fextl::unique_ptr<FEX::HLE::SyscallHandler> CreateHandler(FEXCore::Context::Context *ctx,
|
||||
FEX::HLE::SignalDelegator *_SignalDelegation,
|
||||
std::unique_ptr<MemAllocator> Allocator);
|
||||
fextl::unique_ptr<MemAllocator> Allocator);
|
||||
//////
|
||||
// REGISTER_SYSCALL_IMPL implementation
|
||||
// Given a syscall name + a lambda, and it will generate an strace string, extract number of arguments
|
||||
|
@ -113,7 +113,7 @@ namespace FEX::HLE::x64 {
|
||||
#endif
|
||||
}
|
||||
|
||||
std::unique_ptr<FEX::HLE::SyscallHandler> CreateHandler(FEXCore::Context::Context *ctx, FEX::HLE::SignalDelegator *_SignalDelegation) {
|
||||
return std::make_unique<x64SyscallHandler>(ctx, _SignalDelegation);
|
||||
fextl::unique_ptr<FEX::HLE::SyscallHandler> CreateHandler(FEXCore::Context::Context *ctx, FEX::HLE::SignalDelegator *_SignalDelegation) {
|
||||
return fextl::make_unique<x64SyscallHandler>(ctx, _SignalDelegation);
|
||||
}
|
||||
}
|
||||
|
@ -11,6 +11,7 @@ $end_info$
|
||||
|
||||
#include <FEXCore/HLE/SyscallHandler.h>
|
||||
#include <FEXCore/IR/IR.h>
|
||||
#include <FEXCore/fextl/memory.h>
|
||||
#include <FEXCore/fextl/string.h>
|
||||
|
||||
#include <atomic>
|
||||
@ -70,7 +71,7 @@ class x64SyscallHandler final : public FEX::HLE::SyscallHandler {
|
||||
void RegisterSyscallHandlers();
|
||||
};
|
||||
|
||||
std::unique_ptr<FEX::HLE::SyscallHandler> CreateHandler(FEXCore::Context::Context *ctx, FEX::HLE::SignalDelegator *_SignalDelegation);
|
||||
fextl::unique_ptr<FEX::HLE::SyscallHandler> CreateHandler(FEXCore::Context::Context *ctx, FEX::HLE::SignalDelegator *_SignalDelegation);
|
||||
|
||||
//////
|
||||
// REGISTER_SYSCALL_IMPL implementation
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user