Merge pull request #2747 from Sonicadvance1/non-multiarch-thunks

Thunks: Fixes thunks in non-multiarch
This commit is contained in:
Ryan Houdek authored and GitHub committed 2023-07-13 12:22:30 -07:00
commit 9def04c705
4 files changed
+140 -128

No files matched your search

+63 -63
View File
@@ -6,10 +6,10 @@
"X11"
],
"Overlay": [
"@PREFIX_LIB@/@PREFIX_ARCH@-linux-gnu/libGL.so",
"@PREFIX_LIB@/@PREFIX_ARCH@-linux-gnu/libGL.so.1",
"@PREFIX_LIB@/@PREFIX_ARCH@-linux-gnu/libGL.so.1.2.0",
"@PREFIX_LIB@/@PREFIX_ARCH@-linux-gnu/libGL.so.1.7.0"
"@PREFIX_LIB@/libGL.so",
"@PREFIX_LIB@/libGL.so.1",
"@PREFIX_LIB@/libGL.so.1.2.0",
"@PREFIX_LIB@/libGL.so.1.7.0"
]
},
"GLESv2": {
@@ -18,17 +18,17 @@
"X11"
],
"Overlay": [
"@PREFIX_LIB@/@PREFIX_ARCH@-linux-gnu/libGLESv2.so",
"@PREFIX_LIB@/@PREFIX_ARCH@-linux-gnu/libGLESv2.so.2",
"@PREFIX_LIB@/@PREFIX_ARCH@-linux-gnu/libGLESv2.so.2.0.0"
"@PREFIX_LIB@/libGLESv2.so",
"@PREFIX_LIB@/libGLESv2.so.2",
"@PREFIX_LIB@/libGLESv2.so.2.0.0"
]
},
"X11": {
"Library": "libX11-guest.so",
"Overlay": [
"@PREFIX_LIB@/@PREFIX_ARCH@-linux-gnu/libX11.so",
"@PREFIX_LIB@/@PREFIX_ARCH@-linux-gnu/libX11.so.6",
"@PREFIX_LIB@/@PREFIX_ARCH@-linux-gnu/libX11.so.6.4.0"
"@PREFIX_LIB@/libX11.so",
"@PREFIX_LIB@/libX11.so.6",
"@PREFIX_LIB@/libX11.so.6.4.0"
]
},
"Vulkan": {
@@ -37,8 +37,8 @@
"xcb"
],
"Overlay": [
"@PREFIX_LIB@/@PREFIX_ARCH@-linux-gnu/libvulkan.so",
"@PREFIX_LIB@/@PREFIX_ARCH@-linux-gnu/libvulkan.so.1",
"@PREFIX_LIB@/libvulkan.so",
"@PREFIX_LIB@/libvulkan.so.1",
"@HOME@/.local/share/Steam/ubuntu12_32/steam-runtime/pinned_libs_64/libvulkan.so.1"
],
"Comment": [
@@ -48,137 +48,137 @@
"xcb": {
"Library": "libxcb-guest.so",
"Overlay": [
"@PREFIX_LIB@/@PREFIX_ARCH@-linux-gnu/libxcb.so",
"@PREFIX_LIB@/@PREFIX_ARCH@-linux-gnu/libxcb.so.1",
"@PREFIX_LIB@/@PREFIX_ARCH@-linux-gnu/libxcb.so.1.1.0"
"@PREFIX_LIB@/libxcb.so",
"@PREFIX_LIB@/libxcb.so.1",
"@PREFIX_LIB@/libxcb.so.1.1.0"
]
},
"xcb-dri2": {
"Library": "libxcb-dri2-guest.so",
"Overlay": [
"@PREFIX_LIB@/@PREFIX_ARCH@-linux-gnu/libxcb-dri2.so",
"@PREFIX_LIB@/@PREFIX_ARCH@-linux-gnu/libxcb-dri2.so.0",
"@PREFIX_LIB@/@PREFIX_ARCH@-linux-gnu/libxcb-dri2.so.0.0.0"
"@PREFIX_LIB@/libxcb-dri2.so",
"@PREFIX_LIB@/libxcb-dri2.so.0",
"@PREFIX_LIB@/libxcb-dri2.so.0.0.0"
]
},
"xcb-dri3": {
"Library": "libxcb-dri3-guest.so",
"Overlay": [
"@PREFIX_LIB@/@PREFIX_ARCH@-linux-gnu/libxcb-dri3.so",
"@PREFIX_LIB@/@PREFIX_ARCH@-linux-gnu/libxcb-dri3.so.0",
"@PREFIX_LIB@/@PREFIX_ARCH@-linux-gnu/libxcb-dri3.so.0.0.0"
"@PREFIX_LIB@/libxcb-dri3.so",
"@PREFIX_LIB@/libxcb-dri3.so.0",
"@PREFIX_LIB@/libxcb-dri3.so.0.0.0"
]
},
"xcb-xfixes": {
"Library": "libxcb-xfixes-guest.so",
"Overlay": [
"@PREFIX_LIB@/@PREFIX_ARCH@-linux-gnu/libxcb-xfixes.so",
"@PREFIX_LIB@/@PREFIX_ARCH@-linux-gnu/libxcb-xfixes.so.0",
"@PREFIX_LIB@/@PREFIX_ARCH@-linux-gnu/libxcb-xfixes.so.0.0.0"
"@PREFIX_LIB@/libxcb-xfixes.so",
"@PREFIX_LIB@/libxcb-xfixes.so.0",
"@PREFIX_LIB@/libxcb-xfixes.so.0.0.0"
]
},
"xcb-shm": {
"Library": "libxcb-shm-guest.so",
"Overlay": [
"@PREFIX_LIB@/@PREFIX_ARCH@-linux-gnu/libxcb-shm.so",
"@PREFIX_LIB@/@PREFIX_ARCH@-linux-gnu/libxcb-shm.so.0",
"@PREFIX_LIB@/@PREFIX_ARCH@-linux-gnu/libxcb-shm.so.0.0.0"
"@PREFIX_LIB@/libxcb-shm.so",
"@PREFIX_LIB@/libxcb-shm.so.0",
"@PREFIX_LIB@/libxcb-shm.so.0.0.0"
]
},
"xcb-sync": {
"Library": "libxcb-sync-guest.so",
"Overlay": [
"@PREFIX_LIB@/@PREFIX_ARCH@-linux-gnu/libxcb-sync.so",
"@PREFIX_LIB@/@PREFIX_ARCH@-linux-gnu/libxcb-sync.so.1",
"@PREFIX_LIB@/@PREFIX_ARCH@-linux-gnu/libxcb-sync.so.1.0.0"
"@PREFIX_LIB@/libxcb-sync.so",
"@PREFIX_LIB@/libxcb-sync.so.1",
"@PREFIX_LIB@/libxcb-sync.so.1.0.0"
]
},
"xcb-randr": {
"Library": "libxcb-randr-guest.so",
"Overlay": [
"@PREFIX_LIB@/@PREFIX_ARCH@-linux-gnu/libxcb-randr.so",
"@PREFIX_LIB@/@PREFIX_ARCH@-linux-gnu/libxcb-randr.so.0",
"@PREFIX_LIB@/@PREFIX_ARCH@-linux-gnu/libxcb-randr.so.0.1.0"
"@PREFIX_LIB@/libxcb-randr.so",
"@PREFIX_LIB@/libxcb-randr.so.0",
"@PREFIX_LIB@/libxcb-randr.so.0.1.0"
]
},
"xcb-present": {
"Library": "libxcb-present-guest.so",
"Overlay": [
"@PREFIX_LIB@/@PREFIX_ARCH@-linux-gnu/libxcb-present.so",
"@PREFIX_LIB@/@PREFIX_ARCH@-linux-gnu/libxcb-present.so.0",
"@PREFIX_LIB@/@PREFIX_ARCH@-linux-gnu/libxcb-present.so.0.0.0"
"@PREFIX_LIB@/libxcb-present.so",
"@PREFIX_LIB@/libxcb-present.so.0",
"@PREFIX_LIB@/libxcb-present.so.0.0.0"
]
},
"xcb-glx": {
"Library": "libxcb-glx-guest.so",
"Overlay": [
"@PREFIX_LIB@/@PREFIX_ARCH@-linux-gnu/libxcb-glx.so",
"@PREFIX_LIB@/@PREFIX_ARCH@-linux-gnu/libxcb-glx.so.0",
"@PREFIX_LIB@/@PREFIX_ARCH@-linux-gnu/libxcb-glx.so.0.0.0"
"@PREFIX_LIB@/libxcb-glx.so",
"@PREFIX_LIB@/libxcb-glx.so.0",
"@PREFIX_LIB@/libxcb-glx.so.0.0.0"
]
},
"xshmfence": {
"Library": "libxshmfence-guest.so",
"Overlay": [
"@PREFIX_LIB@/@PREFIX_ARCH@-linux-gnu/libxshmfence.so",
"@PREFIX_LIB@/@PREFIX_ARCH@-linux-gnu/libxshmfence.so.1",
"@PREFIX_LIB@/@PREFIX_ARCH@-linux-gnu/libxshmfence.so.1.0.0"
"@PREFIX_LIB@/libxshmfence.so",
"@PREFIX_LIB@/libxshmfence.so.1",
"@PREFIX_LIB@/libxshmfence.so.1.0.0"
]
},
"drm": {
"Library": "libdrm-guest.so",
"Overlay": [
"@PREFIX_LIB@/@PREFIX_ARCH@-linux-gnu/libdrm.so",
"@PREFIX_LIB@/@PREFIX_ARCH@-linux-gnu/libdrm.so.2",
"@PREFIX_LIB@/@PREFIX_ARCH@-linux-gnu/libdrm.so.2.4.0"
"@PREFIX_LIB@/libdrm.so",
"@PREFIX_LIB@/libdrm.so.2",
"@PREFIX_LIB@/libdrm.so.2.4.0"
]
},
"asound": {
"Library": "libasound-guest.so",
"Overlay": [
"@PREFIX_LIB@/@PREFIX_ARCH@-linux-gnu/libasound.so",
"@PREFIX_LIB@/@PREFIX_ARCH@-linux-gnu/libasound.so.2",
"@PREFIX_LIB@/@PREFIX_ARCH@-linux-gnu/libasound.so.2.0.0"
"@PREFIX_LIB@/libasound.so",
"@PREFIX_LIB@/libasound.so.2",
"@PREFIX_LIB@/libasound.so.2.0.0"
]
},
"Xrender": {
"Library": "libXrender-guest.so",
"Overlay": [
"@PREFIX_LIB@/@PREFIX_ARCH@-linux-gnu/libXrender.so",
"@PREFIX_LIB@/@PREFIX_ARCH@-linux-gnu/libXrender.so.1",
"@PREFIX_LIB@/@PREFIX_ARCH@-linux-gnu/libXrender.so.1.3.0"
"@PREFIX_LIB@/libXrender.so",
"@PREFIX_LIB@/libXrender.so.1",
"@PREFIX_LIB@/libXrender.so.1.3.0"
]
},
"Xext": {
"Library": "libXext-guest.so",
"Overlay": [
"@PREFIX_LIB@/@PREFIX_ARCH@-linux-gnu/libXext.so",
"@PREFIX_LIB@/@PREFIX_ARCH@-linux-gnu/libXext.so.6",
"@PREFIX_LIB@/@PREFIX_ARCH@-linux-gnu/libXext.so.6.4.0"
"@PREFIX_LIB@/libXext.so",
"@PREFIX_LIB@/libXext.so.6",
"@PREFIX_LIB@/libXext.so.6.4.0"
]
},
"Xfixes": {
"Library": "libXfixes-guest.so",
"Overlay": [
"@PREFIX_LIB@/@PREFIX_ARCH@-linux-gnu/libXfixes.so",
"@PREFIX_LIB@/@PREFIX_ARCH@-linux-gnu/libXfixes.so.3",
"@PREFIX_LIB@/@PREFIX_ARCH@-linux-gnu/libXfixes.so.3.1.0"
"@PREFIX_LIB@/libXfixes.so",
"@PREFIX_LIB@/libXfixes.so.3",
"@PREFIX_LIB@/libXfixes.so.3.1.0"
]
},
"OpenCL": {
"Library" : "libOpenCL-guest.so",
"Overlay": [
"@PREFIX_LIB@/@PREFIX_ARCH@-linux-gnu/libOpenCL.so",
"@PREFIX_LIB@/@PREFIX_ARCH@-linux-gnu/libOpenCL.so.1",
"@PREFIX_LIB@/@PREFIX_ARCH@-linux-gnu/libOpenCL.so.1.0.0"
"@PREFIX_LIB@/libOpenCL.so",
"@PREFIX_LIB@/libOpenCL.so.1",
"@PREFIX_LIB@/libOpenCL.so.1.0.0"
]
},
"WaylandClient": {
"Library" : "libwayland-client-guest.so",
"Overlay": [
"@PREFIX_LIB@/@PREFIX_ARCH@-linux-gnu/libwayland-client.so",
"@PREFIX_LIB@/@PREFIX_ARCH@-linux-gnu/libwayland-client.so.0",
"@PREFIX_LIB@/@PREFIX_ARCH@-linux-gnu/libwayland-client.so.0.20.0"
"@PREFIX_LIB@/libwayland-client.so",
"@PREFIX_LIB@/libwayland-client.so.0",
"@PREFIX_LIB@/libwayland-client.so.0.20.0"
]
},
"":{}
@@ -33,6 +33,10 @@ namespace FHU::Filesystem {
return access(Path.c_str(), F_OK) == 0;
}
inline bool ExistsAt(int FD, const fextl::string &Path) {
return faccessat(FD, Path.c_str(), F_OK, 0) == 0;
}
enum class CreateDirectoryResult {
CREATED,
EXISTS,
@@ -15,6 +15,7 @@ $end_info$
#include "LinuxSyscalls/x64/Syscalls.h"
#include <FEXCore/Utils/LogManager.h>
#include <FEXCore/Utils/FileLoading.h>
#include <FEXCore/fextl/fmt.h>
#include <FEXCore/fextl/list.h>
#include <FEXCore/fextl/string.h>
@@ -59,49 +60,62 @@ namespace JSON {
}
namespace FEX::HLE {
struct open_how;
static bool LoadFile(fextl::vector<char> &Data, const fextl::string &Filename) {
int fd = open(Filename.c_str(), O_RDONLY | O_CLOEXEC);
if (fd == -1) {
return false;
}
struct stat buf;
if (fstat(fd, &buf) != 0) {
LogMan::Msg::DFmt("Couldn't load configuration file: fstat");
close(fd);
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);
const auto ReadSize = pread(fd, Data.data(), FileSize, 0);
close(fd);
return ReadSize == FileSize;
bool FileManager::RootFSPathExists(const char* Filepath) {
LOGMAN_THROW_A_FMT(Filepath && Filepath[0] == '/', "Filepath needs to be absolute");
return FHU::Filesystem::ExistsAt(RootFSFD, Filepath + 1);
}
struct ThunkDBObject {
fextl::string LibraryName;
fextl::unordered_set<fextl::string> Depends;
fextl::vector<fextl::string> Overlays;
bool Enabled{};
};
static void LoadThunkDatabase(fextl::unordered_map<fextl::string, ThunkDBObject>& ThunkDB, bool Is64BitMode, bool Global) {
void FileManager::LoadThunkDatabase(fextl::unordered_map<fextl::string, ThunkDBObject>& ThunkDB, bool Global) {
auto ThunkDBPath = FEXCore::Config::GetConfigDirectory(Global) + "ThunksDB.json";
fextl::vector<char> FileData;
if (LoadFile(FileData, ThunkDBPath)) {
if (FEXCore::FileLoading::LoadFile(FileData, ThunkDBPath)) {
FileData.push_back(0);
// If the thunksDB file exists then we need to check if the rootfs supports multi-arch or not.
const bool RootFSIsMultiarch = RootFSPathExists("/usr/lib/x86_64-linux-gnu/") ||
RootFSPathExists("/usr/lib/i386-linux-gnu/");
fextl::vector<fextl::string> PathPrefixes{};
if (RootFSIsMultiarch) {
// Multi-arch debian distros have a fairly complex arrangement of filepaths.
// These fractal out to the combination of library prefixes with arch suffixes.
constexpr static std::array<std::string_view, 4> LibPrefixes = {
"/usr/lib",
"/usr/local/lib",
"/lib",
"/usr/lib/pressure-vessel/overrides/lib",
};
// We only need to generate 32-bit or 64-bit depending on the operating mode.
const auto ArchPrefix = Is64BitMode() ?
"x86_64-linux-gnu" :
"i386-linux-gnu";
for (auto Prefix : LibPrefixes) {
PathPrefixes.emplace_back(fextl::fmt::format("{}/{}", Prefix, ArchPrefix));
}
}
else {
// Non multi-arch supporting distros like Fedora and Debian have a much more simple layout.
// lib/ folders refer to 32-bit library folders.
// li64/ folders refer to 64-bit library folders.
constexpr static std::array<std::string_view, 4> LibPrefixes = {
"/usr",
"/usr/local",
"", // root, the '/' will be appended in the next step.
"/usr/lib/pressure-vessel/overrides",
};
// We only need to generate 32-bit or 64-bit depending on the operating mode.
const auto ArchPrefix = Is64BitMode() ?
"lib64" :
"lib";
for (auto Prefix : LibPrefixes) {
PathPrefixes.emplace_back(fextl::fmt::format("{}/{}", Prefix, ArchPrefix));
}
}
JSON::JsonAllocator Pool {
.PoolObject = {
.init = JSON::PoolInit,
@@ -143,39 +157,24 @@ static void LoadThunkDatabase(fextl::unordered_map<fextl::string, ThunkDBObject>
}
}
else if (ItemName == "Overlay") {
auto AddWithReplacement = [Is64BitMode, HomeDirectory](ThunkDBObject& DBObject, fextl::string LibraryItem) {
constexpr static std::array<std::string_view, 4> LibPrefixes = {
"/usr/lib",
"/usr/local/lib",
"/lib",
"/usr/lib/pressure-vessel/overrides/lib",
};
constexpr static std::array<std::string_view, 2> ArchPrefixes = {
"i386",
"x86_64",
};
auto AddWithReplacement = [HomeDirectory, &PathPrefixes](ThunkDBObject& DBObject, fextl::string LibraryItem) {
// Walk through template string and fill in prefixes from right to left
using namespace std::string_view_literals;
const std::pair PrefixArch { "@PREFIX_ARCH@"sv, LibraryItem.find("@PREFIX_ARCH@") };
const std::pair PrefixHome { "@HOME@"sv, LibraryItem.find("@HOME@") };
const std::pair PrefixLib { "@PREFIX_LIB@"sv, LibraryItem.find("@PREFIX_LIB@") };
fextl::string::size_type PrefixPositions[] = {
PrefixArch.second, PrefixHome.second, PrefixLib.second,
PrefixHome.second, PrefixLib.second,
};
// Sort offsets in descending order to enable safe in-place replacement
std::sort(std::begin(PrefixPositions), std::end(PrefixPositions), std::greater<>{});
for (auto& LibPrefix : LibPrefixes) {
for (auto& LibPrefix : PathPrefixes) {
fextl::string Replacement = LibraryItem;
for (auto PrefixPos : PrefixPositions) {
if (PrefixPos == fextl::string::npos) {
continue;
} else if (PrefixPos == PrefixArch.second) {
Replacement.replace(PrefixPos, PrefixArch.first.size(), ArchPrefixes[Is64BitMode]);
} else if (PrefixPos == PrefixHome.second) {
Replacement.replace(PrefixPos, PrefixHome.first.size(), HomeDirectory);
} else if (PrefixPos == PrefixLib.second) {
@@ -244,13 +243,20 @@ FileManager::FileManager(FEXCore::Context::Context *ctx)
ConfigPaths.emplace_back(FEXCore::Config::GetApplicationConfig(AppName, false));
}
if (!LDPath().empty()) {
RootFSFD = open(LDPath().c_str(), O_DIRECTORY | O_PATH | O_CLOEXEC);
if (RootFSFD == -1) {
RootFSFD = AT_FDCWD;
}
}
fextl::unordered_map<fextl::string, ThunkDBObject> ThunkDB;
LoadThunkDatabase(ThunkDB, Is64BitMode(), true);
LoadThunkDatabase(ThunkDB, Is64BitMode(), false);
LoadThunkDatabase(ThunkDB, true);
LoadThunkDatabase(ThunkDB, false);
for (const auto &Path : ConfigPaths) {
fextl::vector<char> FileData;
if (LoadFile(FileData, Path)) {
if (FEXCore::FileLoading::LoadFile(FileData, Path)) {
JSON::JsonAllocator Pool {
.PoolObject = {
.init = JSON::PoolInit,
@@ -339,13 +345,6 @@ FileManager::FileManager(FEXCore::Context::Context *ctx)
}
UpdatePID(::getpid());
if (!LDPath().empty()) {
RootFSFD = open(LDPath().c_str(), O_DIRECTORY | O_PATH | O_CLOEXEC);
if (RootFSFD == -1) {
RootFSFD = AT_FDCWD;
}
}
}
FileManager::~FileManager() {
@@ -86,6 +86,15 @@ public:
std::pair<int, const char*> GetEmulatedFDPath(int dirfd, const char *pathname, bool FollowSymlink, FDPathTmpData &TmpFilename);
private:
bool RootFSPathExists(const char* Filepath);
struct ThunkDBObject {
fextl::string LibraryName;
fextl::unordered_set<fextl::string> Depends;
fextl::vector<fextl::string> Overlays;
bool Enabled{};
};
void LoadThunkDatabase(fextl::unordered_map<fextl::string, ThunkDBObject>& ThunkDB, bool Global);
FEX::EmulatedFile::EmulatedFDManager EmuFD;
fextl::map<fextl::string, fextl::string, std::less<>> ThunkOverlays;