Resolve most VDSO comments

This commit is contained in:
Ryan Houdek 2022-09-02 14:36:12 -07:00
parent 0869b0aa29
commit c5a7fc1e2a
13 changed files with 288 additions and 186 deletions

View File

@ -202,6 +202,10 @@ namespace FEXCore::Context {
return CTX->AddCustomIREntrypoint(Entrypoint, Handler, Creator, Data);
}
void AppendThunkDefinitions(FEXCore::Context::Context *CTX, std::vector<FEXCore::IR::ThunkDefinition> const& Definitions) {
CTX->AppendThunkDefinitions(Definitions);
}
namespace Debug {
void CompileRIP(FEXCore::Context::Context *CTX, uint64_t RIP) {
CTX->CompileRIP(CTX->ParentThread, RIP);

View File

@ -322,6 +322,8 @@ namespace FEXCore::Context {
IRCaptureCache.SetAOTIRRenamer(CacheRenamer);
}
void AppendThunkDefinitions(std::vector<FEXCore::IR::ThunkDefinition> const& Definitions);
FEXCore::Utils::PooledAllocatorMMap OpDispatcherAllocator;
FEXCore::Utils::PooledAllocatorMMap FrontendAllocator;

View File

@ -1332,6 +1332,11 @@ namespace FEXCore::Context {
}
}
void Context::AppendThunkDefinitions(std::vector<FEXCore::IR::ThunkDefinition> const& Definitions) {
ThunkHandler->AppendThunkDefinitions(Definitions);
}
void ConfigureAOTGen(FEXCore::Core::InternalThreadState *Thread, std::set<uint64_t> *ExternalBranches, uint64_t SectionMaxAddress) {
Thread->FrontendDecoder->SetExternalBranches(ExternalBranches);
Thread->FrontendDecoder->SetSectionMaxAddress(SectionMaxAddress);

View File

@ -17,12 +17,10 @@ $end_info$
#include <cstdint>
#include <dlfcn.h>
#include <elf.h>
#include <Interface/Context/Context.h>
#include "FEXCore/Core/X86Enums.h"
#include <malloc.h>
#include <mutex>
#include <sys/auxv.h>
#include <unordered_map>
#include <memory>
#include <shared_mutex>
@ -69,107 +67,6 @@ extern char __start_HostToGuestTrampolineTemplate[];
extern char __stop_HostToGuestTrampolineTemplate[];
namespace FEXCore {
namespace VDSO {
using TimeType = decltype(::time)*;
using GetTimeOfDayType = decltype(::gettimeofday)*;
using ClockGetTimeType = decltype(::clock_gettime)*;
using ClockGetResType = decltype(::clock_getres)*;
using GetCPUType = decltype(::getcpu)*;
TimeType TimePtr = ::time;
GetTimeOfDayType GetTimeOfDayPtr = ::gettimeofday;
ClockGetTimeType ClockGetTimePtr = ::clock_gettime;
ClockGetResType ClockGetResPtr = ::clock_getres;
GetCPUType GetCPUPtr = ::getcpu;
static void time(void* ArgsRV) {
struct ArgsRV_t {
time_t *a_0;
uint64_t rv;
} *args = reinterpret_cast<ArgsRV_t*>(ArgsRV);
args->rv = TimePtr(args->a_0);
}
static void gettimeofday(void* ArgsRV) {
struct ArgsRV_t {
struct timeval *tv;
struct timezone *tz;
uint64_t rv;
} *args = reinterpret_cast<ArgsRV_t*>(ArgsRV);
args->rv = GetTimeOfDayPtr(args->tv, args->tz);
}
static void clock_gettime(void* ArgsRV) {
struct ArgsRV_t {
clockid_t clk_id;
struct timespec *tp;
uint64_t rv;
} *args = reinterpret_cast<ArgsRV_t*>(ArgsRV);
args->rv = ClockGetTimePtr(args->clk_id, args->tp);
}
static void clock_getres(void* ArgsRV) {
struct ArgsRV_t {
clockid_t clk_id;
struct timespec *tp;
uint64_t rv;
} *args = reinterpret_cast<ArgsRV_t*>(ArgsRV);
args->rv = ClockGetResPtr(args->clk_id, args->tp);
}
static void getcpu(void* ArgsRV) {
struct ArgsRV_t {
uint32_t *cpu;
uint32_t *node;
uint64_t rv;
} *args = reinterpret_cast<ArgsRV_t*>(ArgsRV);
args->rv = GetCPUPtr(args->cpu, args->node);
}
void LoadVDSO() {
void *vdso = dlopen("linux-vdso.so.1", RTLD_LAZY | RTLD_LOCAL | RTLD_NOLOAD);
if (!vdso) {
vdso = dlopen("linux-gate.so.1", RTLD_LAZY | RTLD_LOCAL | RTLD_NOLOAD);
}
if (!vdso) {
// Couldn't load VDSO
return;
}
auto SymbolPtr = dlsym(vdso, "__vdso_time");
if (SymbolPtr) {
TimePtr = reinterpret_cast<TimeType>(SymbolPtr);
}
SymbolPtr = dlsym(vdso, "__vdso_gettimeofday");
if (SymbolPtr) {
GetTimeOfDayPtr = reinterpret_cast<GetTimeOfDayType>(SymbolPtr);
}
SymbolPtr = dlsym(vdso, "__vdso_clock_gettime");
if (SymbolPtr) {
ClockGetTimePtr = reinterpret_cast<ClockGetTimeType>(SymbolPtr);
}
SymbolPtr = dlsym(vdso, "__vdso_clock_getres");
if (SymbolPtr) {
ClockGetResPtr = reinterpret_cast<ClockGetResType>(SymbolPtr);
}
SymbolPtr = dlsym(vdso, "__vdso_getcpu");
if (SymbolPtr) {
GetCPUPtr = reinterpret_cast<GetCPUType>(SymbolPtr);
}
dlclose(vdso);
}
}
struct ExportEntry { uint8_t *sha256; ThunkedFunction* Fn; };
struct TrampolineInstanceInfo {
@ -243,32 +140,6 @@ namespace FEXCore {
{ 0x9b, 0xb2, 0xf4, 0xb4, 0x83, 0x7d, 0x28, 0x93, 0x40, 0xcb, 0xf4, 0x7a, 0x0b, 0x47, 0x85, 0x87, 0xf9, 0xbc, 0xb5, 0x27, 0xca, 0xa6, 0x93, 0xa5, 0xc0, 0x73, 0x27, 0x24, 0xae, 0xc8, 0xb8, 0x5a },
&AllocateHostTrampolineForGuestFunction
},
// VDSO
{
// sha256(libVDSO:time)
{ 0x37, 0x63, 0x46, 0xb0, 0x79, 0x06, 0x5f, 0x9d, 0x00, 0xb6, 0x8d, 0xfd, 0x9e, 0x4a, 0x62, 0xcd, 0x1e, 0x6c, 0xcc, 0x22, 0xcd, 0xb2, 0xc0, 0x17, 0x7d, 0x42, 0x6a, 0x40, 0xd1, 0xeb, 0xfa, 0xe0 },
&VDSO::time
},
{
// sha256(libVDSO:gettimeofday)
{ 0x77, 0x2a, 0xde, 0x1c, 0x13, 0x2d, 0xe9, 0x48, 0xaf, 0xe0, 0xba, 0xcc, 0x6a, 0x89, 0xff, 0xca, 0x4a, 0xdc, 0xd5, 0x63, 0x2c, 0xc5, 0x62, 0x8b, 0x5d, 0xde, 0x0b, 0x15, 0x35, 0xc6, 0xc7, 0x14 },
&VDSO::gettimeofday
},
{
// sha256(libVDSO:clock_gettime)
{ 0x3c, 0x96, 0x9b, 0x2d, 0xc3, 0xad, 0x2b, 0x3b, 0x9c, 0x4e, 0x4d, 0xca, 0x1c, 0xe8, 0x18, 0x4a, 0x12, 0x8a, 0xe4, 0xc1, 0x56, 0x92, 0x73, 0xce, 0x65, 0x85, 0x5f, 0x65, 0x7e, 0x94, 0x26, 0xbe },
&VDSO::clock_gettime
},
{
// sha256(libVDSO:clock_getres)
{ 0xe4, 0xa1, 0xf6, 0x23, 0x35, 0xae, 0xb7, 0xb6, 0xb0, 0x37, 0xc5, 0xc3, 0xa3, 0xfd, 0xbf, 0xa2, 0xa1, 0xc8, 0x95, 0x78, 0xe5, 0x76, 0x86, 0xdb, 0x3e, 0x6c, 0x54, 0xd5, 0x02, 0x60, 0xd8, 0x6d },
&VDSO::clock_getres
},
{
// sha256(libVDSO:getcpu)
{ 0x39, 0x83, 0x39, 0x36, 0x0f, 0x68, 0xd6, 0xfc, 0xc2, 0x3a, 0x97, 0x11, 0x85, 0x09, 0xc7, 0x25, 0xbb, 0x50, 0x49, 0x55, 0x6b, 0x0c, 0x9f, 0x50, 0x37, 0xf5, 0x9d, 0xb0, 0x38, 0x58, 0x57, 0x12 },
&VDSO::getcpu
},
};
// Can't be a string_view. We need to keep a copy of the library name in-case string_view pointer goes away.
@ -449,7 +320,7 @@ namespace FEXCore {
}
}
ThunkedFunction* LookupThunk(const IR::SHA256Sum &sha256) {
ThunkedFunction* LookupThunk(const IR::SHA256Sum &sha256) override {
std::shared_lock lk(ThunksMutex);
@ -462,13 +333,18 @@ namespace FEXCore {
}
}
void RegisterTLSState(FEXCore::Core::InternalThreadState *Thread) {
void RegisterTLSState(FEXCore::Core::InternalThreadState *Thread) override {
::Thread = Thread;
}
void AppendThunkDefinitions(std::vector<FEXCore::IR::ThunkDefinition> const& Definitions) override {
for (auto & Definition : Definitions) {
Thunks.emplace(Definition.Sum, Definition.ThunkFunction);
}
}
};
ThunkHandler* ThunkHandler::Create() {
VDSO::LoadVDSO();
return new ThunkHandler_impl();
}

View File

@ -6,6 +6,10 @@ $end_info$
#pragma once
#include <FEXCore/IR/IR.h>
#include <vector>
namespace FEXCore::Context {
struct Context;
}
@ -28,5 +32,7 @@ namespace FEXCore {
virtual ~ThunkHandler() { }
static ThunkHandler* Create();
virtual void AppendThunkDefinitions(std::vector<FEXCore::IR::ThunkDefinition> const& Definitions) = 0;
};
};

View File

@ -5,6 +5,7 @@
#include <FEXCore/Core/SignalDelegator.h>
#include <FEXCore/Core/CPUID.h>
#include <FEXCore/IR/IR.h>
#include <FEXCore/Utils/CompilerDefs.h>
#include <istream>
@ -280,4 +281,12 @@ namespace FEXCore::Context {
FEX_DEFAULT_VISIBILITY void ConfigureAOTGen(FEXCore::Core::InternalThreadState *Thread, std::set<uint64_t> *ExternalBranches, uint64_t SectionMaxAddress);
FEX_DEFAULT_VISIBILITY CustomIRResult AddCustomIREntrypoint(FEXCore::Context::Context *CTX, uintptr_t Entrypoint, std::function<void(uintptr_t Entrypoint, FEXCore::IR::IREmitter *)> Handler, void *Creator = nullptr, void *Data = nullptr);
/**
* @brief Allows the frontend to register its own thunk handlers independent of what is controlled in the backend.
*
* @param CTX A valid non-null context instance.
* @param Definitions A vector of thunk definitions that the frontend controls
*/
FEX_DEFAULT_VISIBILITY void AppendThunkDefinitions(FEXCore::Context::Context *CTX, std::vector<FEXCore::IR::ThunkDefinition> const& Definitions);
}

View File

@ -413,6 +413,13 @@ struct SHA256Sum final {
}
};
typedef void ThunkedFunction(void* ArgsRv);
struct ThunkDefinition final {
SHA256Sum Sum;
ThunkedFunction *ThunkFunction;
};
class NodeIterator;
/* This iterator can be used to step though nodes.

View File

@ -9,6 +9,7 @@ endif()
add_executable(FEXLoader
FEXLoader.cpp
VDSO_Emulation.cpp
AOT/AOTGenerator.cpp)
# Enable FEX APIs to be used by targets that use target_link_libraries on FEXLoader

View File

@ -19,7 +19,6 @@
#include <FEXCore/Core/CodeLoader.h>
#include <FEXCore/Core/CoreState.h>
#include <FEXCore/Core/X86Enums.h>
#include <FEXCore/Utils/MathUtils.h>
#include <FEXCore/Utils/LogManager.h>
#include <FEXHeaderUtils/Syscalls.h>
@ -46,7 +45,6 @@ class ELFCodeLoader2 final : public FEXCore::CodeLoader {
uintptr_t Entrypoint;
uintptr_t BrkStart;
uintptr_t StackPointer;
void* VDSOStart{};
size_t CalculateTotalElfSize(const std::vector<Elf64_Phdr> &headers)
{
@ -406,28 +404,6 @@ class ELFCodeLoader2 final : public FEXCore::CodeLoader {
Entrypoint = MainElfEntrypoint;
}
if (Is64BitMode()) {
// Load VDSO if we can
FEX_CONFIG_OPT(ThunkGuestLibs, THUNKGUESTLIBS);
auto ThunkGuestPath = std::filesystem::path(ThunkGuestLibs()) / "libVDSO-guest.so";
int VDSOFD = ::open(ThunkGuestPath.string().c_str(), O_RDONLY);
if (VDSOFD != -1) {
// Get file size
size_t VDSOSize = lseek(VDSOFD, 0, SEEK_END);
if (VDSOSize >= 4) {
// Reset to beginning
lseek(VDSOFD, 0, SEEK_SET);
VDSOSize = FEXCore::AlignUp(VDSOSize, 4096);
// Map the VDSO file to memory
VDSOStart = Mapper(nullptr, VDSOSize, PROT_READ, MAP_PRIVATE, VDSOFD, 0);
}
close(VDSOFD);
}
}
// All done
// Setup AuxVars
@ -453,8 +429,8 @@ class ELFCodeLoader2 final : public FEXCore::CodeLoader {
// we don't support vsyscall so we don't set those
//AuxVariables.emplace_back(auxv_t{32, 0}); // AT_SYSINFO - Entry point to syscall
if (VDSOStart) {
AuxVariables.emplace_back(auxv_t{33, reinterpret_cast<uint64_t>(VDSOStart)}); // AT_SYSINFO_EHDR - Address of the start of VDSO
if (VDSOBase) {
AuxVariables.emplace_back(auxv_t{33, reinterpret_cast<uint64_t>(VDSOBase)}); // AT_SYSINFO_EHDR - Address of the start of VDSO
}
}
else {
@ -667,6 +643,10 @@ class ELFCodeLoader2 final : public FEXCore::CodeLoader {
return ElfValid;
}
void SetVDSOBase(void* Base) {
VDSOBase = Base;
}
constexpr static uint64_t BRK_SIZE = 8 * 1024 * 1024;
constexpr static uint64_t STACK_SIZE = 8 * 1024 * 1024;
@ -679,6 +659,7 @@ class ELFCodeLoader2 final : public FEXCore::CodeLoader {
uint64_t ArgumentBackingSize{};
uint64_t EnvironmentBackingSize{};
uint64_t BaseOffset{};
FEX_CONFIG_OPT(AdditionalArguments, ADDITIONALARGUMENTS);
void* VDSOBase{};
FEX_CONFIG_OPT(AdditionalArguments, ADDITIONALARGUMENTS);
};

View File

@ -9,6 +9,7 @@ $end_info$
#include "Common/ArgumentLoader.h"
#include "Common/FEXServerClient.h"
#include "ELFCodeLoader2.h"
#include "VDSO_Emulation.h"
#include "Tests/LinuxSyscalls/LinuxAllocator.h"
#include "Tests/LinuxSyscalls/Syscalls.h"
#include "Tests/LinuxSyscalls/x32/Syscalls.h"
@ -389,6 +390,12 @@ int main(int argc, char **argv, char **const envp) {
auto Mapper = std::bind_front(&FEX::HLE::SyscallHandler::GuestMmap, SyscallHandler.get());
auto Unmapper = std::bind_front(&FEX::HLE::SyscallHandler::GuestMunmap, SyscallHandler.get());
if (Loader.Is64BitMode()) {
// Load VDSO in to memory prior to mapping our ELFs.
void* VDSOBase = FEX::VDSO::LoadVDSOThunks(Mapper);
Loader.SetVDSOBase(VDSOBase);
}
if (!Loader.MapMemory(Mapper, Unmapper)) {
// failed to map
LogMan::Msg::EFmt("Failed to map %d-bit elf file.", Loader.Is64BitMode() ? 64 : 32);
@ -405,6 +412,9 @@ int main(int argc, char **argv, char **const envp) {
FEXCore::Context::SetSyscallHandler(CTX, SyscallHandler.get());
FEXCore::Context::InitCore(CTX, Loader.DefaultRIP(), Loader.GetStackPointer());
// Pass in our VDSO thunks
FEXCore::Context::AppendThunkDefinitions(CTX, FEX::VDSO::GetVDSOThunkDefinitions());
FEXCore::Context::ExitReason ShutdownReason = FEXCore::Context::ExitReason::EXIT_SHUTDOWN;
// There might already be an exit handler, leave it installed

View File

@ -0,0 +1,177 @@
#include "VDSO_Emulation.h"
#include "FEXCore/IR/IR.h"
#include <FEXCore/Config/Config.h>
#include <FEXCore/Utils/MathUtils.h>
#include <FEXCore/Utils/LogManager.h>
#include <dlfcn.h>
#include <fcntl.h>
#include <filesystem>
#include <sys/mman.h>
#include <sys/time.h>
#include <unistd.h>
namespace FEX::VDSO {
using TimeType = decltype(::time)*;
using GetTimeOfDayType = decltype(::gettimeofday)*;
using ClockGetTimeType = decltype(::clock_gettime)*;
using ClockGetResType = decltype(::clock_getres)*;
using GetCPUType = decltype(::getcpu)*;
TimeType TimePtr = ::time;
GetTimeOfDayType GetTimeOfDayPtr = ::gettimeofday;
ClockGetTimeType ClockGetTimePtr = ::clock_gettime;
ClockGetResType ClockGetResPtr = ::clock_getres;
GetCPUType GetCPUPtr = ::getcpu;
static void time(void* ArgsRV) {
struct ArgsRV_t {
time_t *a_0;
uint64_t rv;
} *args = reinterpret_cast<ArgsRV_t*>(ArgsRV);
args->rv = TimePtr(args->a_0);
}
static void gettimeofday(void* ArgsRV) {
struct ArgsRV_t {
struct timeval *tv;
struct timezone *tz;
uint64_t rv;
} *args = reinterpret_cast<ArgsRV_t*>(ArgsRV);
args->rv = GetTimeOfDayPtr(args->tv, args->tz);
}
static void clock_gettime(void* ArgsRV) {
struct ArgsRV_t {
clockid_t clk_id;
struct timespec *tp;
uint64_t rv;
} *args = reinterpret_cast<ArgsRV_t*>(ArgsRV);
args->rv = ClockGetTimePtr(args->clk_id, args->tp);
}
static void clock_getres(void* ArgsRV) {
struct ArgsRV_t {
clockid_t clk_id;
struct timespec *tp;
uint64_t rv;
} *args = reinterpret_cast<ArgsRV_t*>(ArgsRV);
args->rv = ClockGetResPtr(args->clk_id, args->tp);
}
static void getcpu(void* ArgsRV) {
struct ArgsRV_t {
uint32_t *cpu;
uint32_t *node;
uint64_t rv;
} *args = reinterpret_cast<ArgsRV_t*>(ArgsRV);
args->rv = GetCPUPtr(args->cpu, args->node);
}
void LoadHostVDSO() {
void *vdso = dlopen("linux-vdso.so.1", RTLD_LAZY | RTLD_LOCAL | RTLD_NOLOAD);
if (!vdso) {
vdso = dlopen("linux-gate.so.1", RTLD_LAZY | RTLD_LOCAL | RTLD_NOLOAD);
}
if (!vdso) {
// We couldn't load VDSO, fallback to C implementations. Which will still be faster than emulated libc versions.
LogMan::Msg::IFmt("linux-vdso implementation falling back to libc. Consider enabling VDSO in your kernel.");
return;
}
auto SymbolPtr = dlsym(vdso, "__vdso_time");
if (SymbolPtr) {
TimePtr = reinterpret_cast<TimeType>(SymbolPtr);
}
SymbolPtr = dlsym(vdso, "__vdso_gettimeofday");
if (SymbolPtr) {
GetTimeOfDayPtr = reinterpret_cast<GetTimeOfDayType>(SymbolPtr);
}
SymbolPtr = dlsym(vdso, "__vdso_clock_gettime");
if (SymbolPtr) {
ClockGetTimePtr = reinterpret_cast<ClockGetTimeType>(SymbolPtr);
}
SymbolPtr = dlsym(vdso, "__vdso_clock_getres");
if (SymbolPtr) {
ClockGetResPtr = reinterpret_cast<ClockGetResType>(SymbolPtr);
}
SymbolPtr = dlsym(vdso, "__vdso_getcpu");
if (SymbolPtr) {
GetCPUPtr = reinterpret_cast<GetCPUType>(SymbolPtr);
}
dlclose(vdso);
}
static std::vector<FEXCore::IR::ThunkDefinition> VDSODefinitions = {
{
// sha256(libVDSO:time)
{ 0x37, 0x63, 0x46, 0xb0, 0x79, 0x06, 0x5f, 0x9d, 0x00, 0xb6, 0x8d, 0xfd, 0x9e, 0x4a, 0x62, 0xcd, 0x1e, 0x6c, 0xcc, 0x22, 0xcd, 0xb2, 0xc0, 0x17, 0x7d, 0x42, 0x6a, 0x40, 0xd1, 0xeb, 0xfa, 0xe0 },
&FEX::VDSO::time
},
{
// sha256(libVDSO:gettimeofday)
{ 0x77, 0x2a, 0xde, 0x1c, 0x13, 0x2d, 0xe9, 0x48, 0xaf, 0xe0, 0xba, 0xcc, 0x6a, 0x89, 0xff, 0xca, 0x4a, 0xdc, 0xd5, 0x63, 0x2c, 0xc5, 0x62, 0x8b, 0x5d, 0xde, 0x0b, 0x15, 0x35, 0xc6, 0xc7, 0x14 },
&FEX::VDSO::gettimeofday
},
{
// sha256(libVDSO:clock_gettime)
{ 0x3c, 0x96, 0x9b, 0x2d, 0xc3, 0xad, 0x2b, 0x3b, 0x9c, 0x4e, 0x4d, 0xca, 0x1c, 0xe8, 0x18, 0x4a, 0x12, 0x8a, 0xe4, 0xc1, 0x56, 0x92, 0x73, 0xce, 0x65, 0x85, 0x5f, 0x65, 0x7e, 0x94, 0x26, 0xbe },
&FEX::VDSO::clock_gettime
},
{
// sha256(libVDSO:clock_getres)
{ 0xe4, 0xa1, 0xf6, 0x23, 0x35, 0xae, 0xb7, 0xb6, 0xb0, 0x37, 0xc5, 0xc3, 0xa3, 0xfd, 0xbf, 0xa2, 0xa1, 0xc8, 0x95, 0x78, 0xe5, 0x76, 0x86, 0xdb, 0x3e, 0x6c, 0x54, 0xd5, 0x02, 0x60, 0xd8, 0x6d },
&FEX::VDSO::clock_getres
},
{
// sha256(libVDSO:getcpu)
{ 0x39, 0x83, 0x39, 0x36, 0x0f, 0x68, 0xd6, 0xfc, 0xc2, 0x3a, 0x97, 0x11, 0x85, 0x09, 0xc7, 0x25, 0xbb, 0x50, 0x49, 0x55, 0x6b, 0x0c, 0x9f, 0x50, 0x37, 0xf5, 0x9d, 0xb0, 0x38, 0x58, 0x57, 0x12 },
&FEX::VDSO::getcpu
},
};
void* LoadVDSOThunks(MapperFn Mapper) {
void* VDSOBase{};
FEX_CONFIG_OPT(ThunkGuestLibs, THUNKGUESTLIBS);
// Load VDSO if we can
auto ThunkGuestPath = std::filesystem::path(ThunkGuestLibs()) / "libVDSO-guest.so";
int VDSOFD = ::open(ThunkGuestPath.string().c_str(), O_RDONLY);
if (VDSOFD != -1) {
// Get file size
size_t VDSOSize = lseek(VDSOFD, 0, SEEK_END);
if (VDSOSize >= 4) {
// Reset to beginning
lseek(VDSOFD, 0, SEEK_SET);
VDSOSize = FEXCore::AlignUp(VDSOSize, 4096);
// Map the VDSO file to memory
VDSOBase = Mapper(nullptr, VDSOSize, PROT_READ, MAP_PRIVATE, VDSOFD, 0);
// Since we found our VDSO thunk library, find our host VDSO function implementations.
LoadHostVDSO();
}
close(VDSOFD);
}
return VDSOBase;
}
std::vector<FEXCore::IR::ThunkDefinition> const& GetVDSOThunkDefinitions() {
return VDSODefinitions;
}
}

View File

@ -0,0 +1,9 @@
#pragma once
#include <FEXCore/IR/IR.h>
namespace FEX::VDSO {
using MapperFn = std::function<void *(void *addr, size_t length, int prot, int flags, int fd, off_t offset)>;
void* LoadVDSOThunks(MapperFn Mapper);
std::vector<FEXCore::IR::ThunkDefinition> const& GetVDSOThunkDefinitions();
}

View File

@ -56,7 +56,7 @@ function(generate NAME SOURCE_FILE)
set(GEN_${NAME} ${OUTPUTS} PARENT_SCOPE)
endfunction()
function(add_guest_lib NAME)
function(add_guest_lib NAME SONAME)
set (SOURCE_FILE ../lib${NAME}/lib${NAME}_Guest.cpp)
get_filename_component(SOURCE_FILE_ABS "${SOURCE_FILE}" ABSOLUTE)
@ -79,10 +79,28 @@ function(add_guest_lib NAME)
## Make signed overflow well defined 2's complement overflow
target_compile_options(${NAME}-guest PRIVATE -fwrapv)
# Add linker script if set
if (EXISTS "${SOURCE_LDS_FILE_ABS}")
target_link_options(VDSO-guest PRIVATE "-T" "${CMAKE_CURRENT_SOURCE_DIR}/../lib${NAME}/lib${NAME}_Guest.lds")
target_link_options(${NAME}-guest PRIVATE "-T" "${CMAKE_CURRENT_SOURCE_DIR}/../lib${NAME}/lib${NAME}_Guest.lds")
endif()
# We need to override the soname for the linker.
# Our guest thunk libraries are named `lib<Thunk>-guest`.
# Once we override the loaded name, the guest is free to dlopen again by SONAME rather than filepath.
# eg:
# dlopen("libGL.so.1", RTLD_GLOBAL | RTLD_NOW); -> We override this `libGL.so.1` to `libGL-guest.so`
# Later on in the program, it can do:
# dlopen("libGL.so.1", RTLD_GLOBAL | RTLD_NOLOAD);
# This second dlopen will only check to see if the previous load has made the library resident
# Searching for SONAME in the process.
#
# Additionally, VDSO can only be opened by SONAME.
# This means it will only ever open the handle with `dlopen("linux-vdso.so.1", RTLD_GLOBAL | RTLD_NOLOAD);
# Note that this doesn't have a lib prefix, and also since it doesn't exist on the filesystem, it can never
# Actually load from a path.
target_link_options(${NAME}-guest PRIVATE "LINKER:-soname,${SONAME}")
set_target_properties(${NAME}-guest PROPERTIES NO_SONAME ON)
if (GENERATE_GUEST_INSTALL_TARGETS)
install(TARGETS ${NAME}-guest DESTINATION ${DATA_DIRECTORY}/GuestThunks/)
endif()
@ -95,13 +113,13 @@ endfunction()
#add_guest_lib(fex_malloc)
generate(libasound ${CMAKE_CURRENT_SOURCE_DIR}/../libasound/libasound_interface.cpp thunks function_packs function_packs_public)
add_guest_lib(asound)
add_guest_lib(asound "libasound.so.2")
generate(libEGL ${CMAKE_CURRENT_SOURCE_DIR}/../libEGL/libEGL_interface.cpp thunks function_packs function_packs_public)
add_guest_lib(EGL)
add_guest_lib(EGL "libEGL.so.1")
generate(libGL ${CMAKE_CURRENT_SOURCE_DIR}/../libGL/libGL_interface.cpp thunks function_packs function_packs_public symbol_list)
add_guest_lib(GL)
add_guest_lib(GL "libGL.so.1")
# libGL must pull in libX11.so, so generate a placeholder libX11.so to link against
add_library(X11 SHARED ../libX11/libX11_NativeGuest.cpp)
@ -124,71 +142,68 @@ set(X11_VERSION_MINOR ${CMAKE_MATCH_2})
set(X11_VERSION_PATCH ${CMAKE_MATCH_3})
generate(libX11 ${CMAKE_CURRENT_SOURCE_DIR}/../libX11/libX11_interface.cpp thunks function_packs function_packs_public)
add_guest_lib(X11)
add_guest_lib(X11 "libX11.so.6")
target_compile_definitions(libX11-guest-deps INTERFACE -DX11_VERSION_MAJOR=${X11_VERSION_MAJOR})
target_compile_definitions(libX11-guest-deps INTERFACE -DX11_VERSION_MINOR=${X11_VERSION_MINOR})
target_compile_definitions(libX11-guest-deps INTERFACE -DX11_VERSION_PATCH=${X11_VERSION_PATCH})
generate(libXext ${CMAKE_CURRENT_SOURCE_DIR}/../libXext/libXext_interface.cpp thunks function_packs function_packs_public)
add_guest_lib(Xext)
add_guest_lib(Xext "libXext.so.6")
target_compile_definitions(libXext-guest-deps INTERFACE -DX11_VERSION_MAJOR=${X11_VERSION_MAJOR})
target_compile_definitions(libXext-guest-deps INTERFACE -DX11_VERSION_MINOR=${X11_VERSION_MINOR})
target_compile_definitions(libXext-guest-deps INTERFACE -DX11_VERSION_PATCH=${X11_VERSION_PATCH})
generate(libXrender ${CMAKE_CURRENT_SOURCE_DIR}/../libXrender/libXrender_interface.cpp thunks function_packs function_packs_public)
add_guest_lib(Xrender)
add_guest_lib(Xrender "libXrender.so.1")
generate(libXfixes ${CMAKE_CURRENT_SOURCE_DIR}/../libXfixes/libXfixes_interface.cpp thunks function_packs function_packs_public)
add_guest_lib(Xfixes)
add_guest_lib(Xfixes "libXfixes.so.3")
generate(libvulkan ${CMAKE_CURRENT_SOURCE_DIR}/../libvulkan/libvulkan_interface.cpp thunks function_packs function_packs_public symbol_list)
target_include_directories(libvulkan-guest-deps INTERFACE ${FEX_PROJECT_SOURCE_DIR}/External/Vulkan-Headers/include/)
add_guest_lib(vulkan)
add_guest_lib(vulkan "libvulkan.so.1")
generate(libxcb ${CMAKE_CURRENT_SOURCE_DIR}/../libxcb/libxcb_interface.cpp thunks function_packs function_packs_public)
add_guest_lib(xcb)
add_guest_lib(xcb "libxcb.so.1")
generate(libxcb-dri2 ${CMAKE_CURRENT_SOURCE_DIR}/../libxcb-dri2/libxcb-dri2_interface.cpp thunks function_packs function_packs_public)
add_guest_lib(xcb-dri2)
add_guest_lib(xcb-dri2 "libxcb-dri2.so.0")
generate(libxcb-dri3 ${CMAKE_CURRENT_SOURCE_DIR}/../libxcb-dri3/libxcb-dri3_interface.cpp thunks function_packs function_packs_public)
add_guest_lib(xcb-dri3)
add_guest_lib(xcb-dri3 "libxcb-dri3.so.0")
generate(libxcb-xfixes ${CMAKE_CURRENT_SOURCE_DIR}/../libxcb-xfixes/libxcb-xfixes_interface.cpp thunks function_packs function_packs_public)
add_guest_lib(xcb-xfixes)
add_guest_lib(xcb-xfixes "libxcb-xfixes.so.0")
generate(libxcb-shm ${CMAKE_CURRENT_SOURCE_DIR}/../libxcb-shm/libxcb-shm_interface.cpp thunks function_packs function_packs_public)
add_guest_lib(xcb-shm)
add_guest_lib(xcb-shm "libxcb-shm.so.0")
generate(libxcb-sync ${CMAKE_CURRENT_SOURCE_DIR}/../libxcb-sync/libxcb-sync_interface.cpp thunks function_packs function_packs_public)
add_guest_lib(xcb-sync)
add_guest_lib(xcb-sync "libxcb-sync.so.1")
generate(libxcb-present ${CMAKE_CURRENT_SOURCE_DIR}/../libxcb-present/libxcb-present_interface.cpp thunks function_packs function_packs_public)
add_guest_lib(xcb-present)
add_guest_lib(xcb-present "libxcb-present.so.0")
generate(libxcb-randr ${CMAKE_CURRENT_SOURCE_DIR}/../libxcb-randr/libxcb-randr_interface.cpp thunks function_packs function_packs_public)
add_guest_lib(xcb-randr)
add_guest_lib(xcb-randr "libxcb-randr.so.0")
generate(libxcb-glx ${CMAKE_CURRENT_SOURCE_DIR}/../libxcb-glx/libxcb-glx_interface.cpp thunks function_packs function_packs_public)
add_guest_lib(xcb-glx)
add_guest_lib(xcb-glx "libxcb-glx.so.0")
generate(libxshmfence ${CMAKE_CURRENT_SOURCE_DIR}/../libxshmfence/libxshmfence_interface.cpp thunks function_packs function_packs_public)
add_guest_lib(xshmfence)
add_guest_lib(xshmfence "libxshmfence.so.1")
generate(libdrm ${CMAKE_CURRENT_SOURCE_DIR}/../libdrm/libdrm_interface.cpp thunks function_packs function_packs_public)
target_include_directories(libdrm-guest-deps INTERFACE /usr/include/drm/)
target_include_directories(libdrm-guest-deps INTERFACE /usr/include/libdrm/)
add_guest_lib(drm)
add_guest_lib(drm "libdrm.so.2")
generate(libVDSO ${CMAKE_CURRENT_SOURCE_DIR}/../libVDSO/libVDSO_interface.cpp thunks function_packs function_packs_public)
add_guest_lib(VDSO)
add_guest_lib(VDSO "linux-vdso.so.1")
# Can't use a stack protector because otherwise cross-compiling fails
# Not necessary anyway because it only trampolines
target_compile_options(VDSO-guest PRIVATE "-fno-stack-protector")
target_link_options(VDSO-guest PRIVATE "-T" "${CMAKE_CURRENT_SOURCE_DIR}/../libVDSO/libVDSO_Guest.lds" "-nostdlib" "-Wl,-soname,linux-vdso.so.1"
"-Wl,--no-undefined" "-Wl,-z,max-page-size=4096" "-Wl,--hash-style=both")
# Need to override SONAME in linker options
set_target_properties(VDSO-guest PROPERTIES NO_SONAME ON)
target_link_options(VDSO-guest PRIVATE "-T" "${CMAKE_CURRENT_SOURCE_DIR}/../libVDSO/libVDSO_Guest.lds" "-nostdlib"
"LINKER:--no-undefined" "LINKER:-z,max-page-size=4096" "LINKER:--hash-style=both")