Files
FEX-Emu--FEX/Source/Tools/LinuxEmulation/LinuxSyscalls/x32/Syscalls.h
T
Alyssa Rosenzweig a10f984b1c clang-format: left-align escaped newlines
alternative to #3638. this is theoretically better for side-by-side diffs. in
practice it may make other diffs worse since all the \'s change when part of the
macro change.

Signed-off-by: Alyssa Rosenzweig <alyssa@rosenzweig.io>
2024-05-20 09:47:21 -04:00

131 lines
4.8 KiB
C++

// SPDX-License-Identifier: MIT
/*
$info$
tags: LinuxSyscalls|syscalls-x86-32
$end_info$
*/
#pragma once
#include <FEXCore/fextl/memory.h>
#include <FEXCore/fextl/string.h>
#include "LinuxSyscalls/Syscalls.h"
#include <memory>
#include <stddef.h>
#include <stdint.h>
#include <sys/types.h>
namespace FEXCore {
namespace Context {
class Context;
}
namespace Core {
struct CpuStateFrame;
}
} // namespace FEXCore
namespace FEX::HLE {
class SignalDelegator;
}
namespace FEX::HLE::x32 {
#include "SyscallsEnum.h"
class x32SyscallHandler final : public FEX::HLE::SyscallHandler {
public:
x32SyscallHandler(FEXCore::Context::Context* ctx, FEX::HLE::SignalDelegator* _SignalDelegation, fextl::unique_ptr<MemAllocator> Allocator);
FEX::HLE::MemAllocator* GetAllocator() {
return AllocHandler.get();
}
void* GuestMmap(FEXCore::Core::InternalThreadState* Thread, void* addr, size_t length, int prot, int flags, int fd, off_t offset) override;
int GuestMunmap(FEXCore::Core::InternalThreadState* Thread, void* addr, uint64_t length) override;
void RegisterSyscall_32(int SyscallNumber, int32_t HostSyscallNumber, FEXCore::IR::SyscallFlags Flags,
#ifdef DEBUG_STRACE
const fextl::string& TraceFormatString,
#endif
void* SyscallHandler, int ArgumentCount) override {
auto& Def = Definitions.at(SyscallNumber);
#if defined(ASSERTIONS_ENABLED) && ASSERTIONS_ENABLED
auto cvt = [](auto in) {
union {
decltype(in) val;
void* raw;
} raw;
raw.val = in;
return raw.raw;
};
LOGMAN_THROW_A_FMT(Def.Ptr == cvt(&UnimplementedSyscall), "Oops overwriting sysall problem, {}", SyscallNumber);
#endif
Def.Ptr = SyscallHandler;
Def.NumArgs = ArgumentCount;
Def.Flags = Flags;
Def.HostSyscallNumber = HostSyscallNumber;
#ifdef DEBUG_STRACE
Def.StraceFmt = TraceFormatString;
#endif
}
private:
void RegisterSyscallHandlers();
fextl::unique_ptr<MemAllocator> AllocHandler {};
};
fextl::unique_ptr<FEX::HLE::SyscallHandler>
CreateHandler(FEXCore::Context::Context* ctx, FEX::HLE::SignalDelegator* _SignalDelegation, 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
// and register it as a syscall handler
//////
// RegisterSyscall base
// Deduces return, args... from the function passed
// Does not work with lambas, because they are objects with operator (), not functions
template<typename R, typename... Args>
void RegisterSyscall(SyscallHandler* Handler, int SyscallNumber, int32_t HostSyscallNumber, FEXCore::IR::SyscallFlags Flags,
const char* Name, R (*fn)(FEXCore::Core::CpuStateFrame* Frame, Args...)) {
#ifdef DEBUG_STRACE
auto TraceFormatString = fextl::string(Name) + "(" + CollectArgsFmtString<Args...>() + ") = %ld";
#endif
Handler->RegisterSyscall_32(SyscallNumber, HostSyscallNumber, Flags,
#ifdef DEBUG_STRACE
TraceFormatString,
#endif
reinterpret_cast<void*>(fn), sizeof...(Args));
}
// Generic RegisterSyscall for lambdas
// Non-capturing lambdas can be cast to function pointers, but this does not happen on argument matching
// This is some glue logic that will cast a lambda and call the base RegisterSyscall implementation
template<class F>
void RegisterSyscall(SyscallHandler* _Handler, int num, int32_t HostSyscallNumber, FEXCore::IR::SyscallFlags Flags, const char* name, F f) {
RegisterSyscall(_Handler, num, HostSyscallNumber, Flags, name, +f);
}
} // namespace FEX::HLE::x32
// Registers syscall for 32bit only
#define REGISTER_SYSCALL_IMPL_X32(name, lambda) REGISTER_SYSCALL_IMPL_X32_INTERNAL(name, ~0, FEXCore::IR::SyscallFlags::DEFAULT, lambda)
#define REGISTER_SYSCALL_IMPL_X32_PASS(name, lambda) \
REGISTER_SYSCALL_IMPL_X32_INTERNAL(name, SYSCALL_DEF(name), FEXCore::IR::SyscallFlags::DEFAULT, lambda)
#define REGISTER_SYSCALL_IMPL_X32_PASS_MANUAL(name, hostname, lambda) \
REGISTER_SYSCALL_IMPL_X32_INTERNAL(name, SYSCALL_DEF(hostname), FEXCore::IR::SyscallFlags::DEFAULT, lambda)
#define REGISTER_SYSCALL_IMPL_X32_FLAGS(name, flags, lambda) REGISTER_SYSCALL_IMPL_X32_INTERNAL(name, ~0, flags, lambda)
#define REGISTER_SYSCALL_IMPL_X32_PASS_FLAGS(name, flags, lambda) REGISTER_SYSCALL_IMPL_X32_INTERNAL(name, SYSCALL_DEF(name), flags, lambda)
#define REGISTER_SYSCALL_IMPL_X32_PASS_MANUAL_FLAGS(name, hostname, flags, lambda) \
REGISTER_SYSCALL_IMPL_X32_INTERNAL(name, SYSCALL_DEF(hostname), flags, lambda)
#define REGISTER_SYSCALL_IMPL_X32_INTERNAL(name, number, flags, lambda) \
do { \
FEX::HLE::x32::RegisterSyscall(Handler, x32::SYSCALL_x86_##name, number, flags, #name, lambda); \
} while (false)