mirror of
https://github.com/shadps4-emu/shadPS4.git
synced 2025-07-27 04:25:12 +00:00
Merge cac372eb01
into 1b952bf173
This commit is contained in:
commit
57fc14fbce
@ -402,10 +402,7 @@ static const std::unordered_map<ZydisMnemonic, PatchInfo> Patches = {
|
|||||||
{ZYDIS_MNEMONIC_INSERTQ, {FilterNoSSE4a, GenerateINSERTQ, true}},
|
{ZYDIS_MNEMONIC_INSERTQ, {FilterNoSSE4a, GenerateINSERTQ, true}},
|
||||||
|
|
||||||
#if defined(_WIN32)
|
#if defined(_WIN32)
|
||||||
// Windows needs a trampoline.
|
|
||||||
{ZYDIS_MNEMONIC_MOV, {FilterTcbAccess, GenerateTcbAccess, true}},
|
{ZYDIS_MNEMONIC_MOV, {FilterTcbAccess, GenerateTcbAccess, true}},
|
||||||
#elif !defined(__APPLE__)
|
|
||||||
{ZYDIS_MNEMONIC_MOV, {FilterTcbAccess, GenerateTcbAccess, false}},
|
|
||||||
#endif
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -674,24 +671,12 @@ static bool TryPatchJit(void* code_address) {
|
|||||||
return TryPatch(code, module).first;
|
return TryPatch(code, module).first;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void TryPatchAot(void* code_address, u64 code_size) {
|
#ifdef _WIN32
|
||||||
auto* code = static_cast<u8*>(code_address);
|
// Used for patching TCB accesses on Windows.
|
||||||
auto* module = GetModule(code);
|
|
||||||
if (module == nullptr) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::unique_lock lock{module->mutex};
|
|
||||||
|
|
||||||
const auto* end = code + code_size;
|
|
||||||
while (code < end) {
|
|
||||||
code += TryPatch(code, module).second;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static bool PatchesAccessViolationHandler(void* context, void* /* fault_address */) {
|
static bool PatchesAccessViolationHandler(void* context, void* /* fault_address */) {
|
||||||
return TryPatchJit(Common::GetRip(context));
|
return TryPatchJit(Common::GetRip(context));
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
static bool PatchesIllegalInstructionHandler(void* context) {
|
static bool PatchesIllegalInstructionHandler(void* context) {
|
||||||
void* code_address = Common::GetRip(context);
|
void* code_address = Common::GetRip(context);
|
||||||
@ -719,7 +704,9 @@ static void PatchesInit() {
|
|||||||
auto* signals = Signals::Instance();
|
auto* signals = Signals::Instance();
|
||||||
// Should be called last.
|
// Should be called last.
|
||||||
constexpr auto priority = std::numeric_limits<u32>::max();
|
constexpr auto priority = std::numeric_limits<u32>::max();
|
||||||
|
#ifdef _WIN32
|
||||||
signals->RegisterAccessViolationHandler(PatchesAccessViolationHandler, priority);
|
signals->RegisterAccessViolationHandler(PatchesAccessViolationHandler, priority);
|
||||||
|
#endif
|
||||||
signals->RegisterIllegalInstructionHandler(PatchesIllegalInstructionHandler, priority);
|
signals->RegisterIllegalInstructionHandler(PatchesIllegalInstructionHandler, priority);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -735,14 +722,4 @@ void RegisterPatchModule(void* module_ptr, u64 module_size, void* trampoline_are
|
|||||||
trampoline_area_size));
|
trampoline_area_size));
|
||||||
}
|
}
|
||||||
|
|
||||||
void PrePatchInstructions(u64 segment_addr, u64 segment_size) {
|
|
||||||
#if !defined(_WIN32) && !defined(__APPLE__)
|
|
||||||
// Linux and others have an FS segment pointing to valid memory, so continue to do full
|
|
||||||
// ahead-of-time patching for now until a better solution is worked out.
|
|
||||||
if (!Patches.empty()) {
|
|
||||||
TryPatchAot(reinterpret_cast<void*>(segment_addr), segment_size);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace Core
|
} // namespace Core
|
||||||
|
@ -11,7 +11,4 @@ namespace Core {
|
|||||||
void RegisterPatchModule(void* module_ptr, u64 module_size, void* trampoline_area_ptr,
|
void RegisterPatchModule(void* module_ptr, u64 module_size, void* trampoline_area_ptr,
|
||||||
u64 trampoline_area_size);
|
u64 trampoline_area_size);
|
||||||
|
|
||||||
/// Applies CPU patches that need to be done before beginning executions.
|
|
||||||
void PrePatchInstructions(u64 segment_addr, u64 segment_size);
|
|
||||||
|
|
||||||
} // namespace Core
|
} // namespace Core
|
||||||
|
@ -163,11 +163,6 @@ void Module::LoadModuleToMemory(u32& max_tls_index) {
|
|||||||
LOG_INFO(Core_Linker, "segment_mode ..........: {}", segment_mode);
|
LOG_INFO(Core_Linker, "segment_mode ..........: {}", segment_mode);
|
||||||
|
|
||||||
add_segment(elf_pheader[i]);
|
add_segment(elf_pheader[i]);
|
||||||
#ifdef ARCH_X86_64
|
|
||||||
if (elf_pheader[i].p_flags & PF_EXEC) {
|
|
||||||
PrePatchInstructions(segment_addr, segment_file_size);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case PT_DYNAMIC:
|
case PT_DYNAMIC:
|
||||||
|
@ -46,6 +46,8 @@ Tcb* GetTcbBase() {
|
|||||||
return reinterpret_cast<Tcb*>(TlsGetValue(GetTcbKey()));
|
return reinterpret_cast<Tcb*>(TlsGetValue(GetTcbKey()));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void SwapTcb() {}
|
||||||
|
|
||||||
#elif defined(__APPLE__) && defined(ARCH_X86_64)
|
#elif defined(__APPLE__) && defined(ARCH_X86_64)
|
||||||
|
|
||||||
// Apple x86_64
|
// Apple x86_64
|
||||||
@ -151,6 +153,8 @@ Tcb* GetTcbBase() {
|
|||||||
return tcb;
|
return tcb;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void SwapTcb() {}
|
||||||
|
|
||||||
#elif defined(ARCH_X86_64)
|
#elif defined(ARCH_X86_64)
|
||||||
|
|
||||||
// Other POSIX x86_64
|
// Other POSIX x86_64
|
||||||
@ -165,6 +169,17 @@ Tcb* GetTcbBase() {
|
|||||||
return tcb;
|
return tcb;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void SwapTcb() {
|
||||||
|
void* fs;
|
||||||
|
void* gs;
|
||||||
|
asm volatile("rdfsbase %0" : "=r"(fs)::"memory");
|
||||||
|
asm volatile("rdgsbase %0" : "=r"(gs)::"memory");
|
||||||
|
|
||||||
|
// Swap FS and GS
|
||||||
|
asm volatile("wrfsbase %0" ::"r"(gs) : "memory");
|
||||||
|
asm volatile("wrgsbase %0" ::"r"(fs) : "memory");
|
||||||
|
}
|
||||||
|
|
||||||
#else
|
#else
|
||||||
|
|
||||||
// POSIX non-x86_64
|
// POSIX non-x86_64
|
||||||
@ -191,6 +206,8 @@ Tcb* GetTcbBase() {
|
|||||||
return static_cast<Tcb*>(pthread_getspecific(GetTcbKey()));
|
return static_cast<Tcb*>(pthread_getspecific(GetTcbKey()));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void SwapTcb() {}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
thread_local std::once_flag init_tls_flag;
|
thread_local std::once_flag init_tls_flag;
|
||||||
|
@ -39,6 +39,9 @@ void SetTcbBase(void* image_address);
|
|||||||
/// Retrieves Tcb structure for the calling thread.
|
/// Retrieves Tcb structure for the calling thread.
|
||||||
Tcb* GetTcbBase();
|
Tcb* GetTcbBase();
|
||||||
|
|
||||||
|
/// Swaps the TCB in or out of the fs register, if required by the platform.
|
||||||
|
void SwapTcb();
|
||||||
|
|
||||||
/// Makes sure TLS is initialized for the thread before entering guest.
|
/// Makes sure TLS is initialized for the thread before entering guest.
|
||||||
void EnsureThreadInitialized();
|
void EnsureThreadInitialized();
|
||||||
|
|
||||||
@ -54,7 +57,17 @@ ReturnType ExecuteGuest(PS4_SYSV_ABI ReturnType (*func)(FuncArgs...), CallArgs&&
|
|||||||
EnsureThreadInitialized();
|
EnsureThreadInitialized();
|
||||||
// clear stack to avoid trash from EnsureThreadInitialized
|
// clear stack to avoid trash from EnsureThreadInitialized
|
||||||
ClearStack<13_KB>();
|
ClearStack<13_KB>();
|
||||||
return func(std::forward<CallArgs>(args)...);
|
|
||||||
|
if constexpr (std::is_same_v<ReturnType, void>) {
|
||||||
|
SwapTcb();
|
||||||
|
func(std::forward<CallArgs>(args)...);
|
||||||
|
SwapTcb();
|
||||||
|
} else {
|
||||||
|
SwapTcb();
|
||||||
|
auto ret = func(std::forward<CallArgs>(args)...);
|
||||||
|
SwapTcb();
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
template <class F, F f>
|
template <class F, F f>
|
||||||
@ -63,7 +76,16 @@ struct HostCallWrapperImpl;
|
|||||||
template <class ReturnType, class... Args, PS4_SYSV_ABI ReturnType (*func)(Args...)>
|
template <class ReturnType, class... Args, PS4_SYSV_ABI ReturnType (*func)(Args...)>
|
||||||
struct HostCallWrapperImpl<PS4_SYSV_ABI ReturnType (*)(Args...), func> {
|
struct HostCallWrapperImpl<PS4_SYSV_ABI ReturnType (*)(Args...), func> {
|
||||||
static ReturnType PS4_SYSV_ABI wrap(Args... args) {
|
static ReturnType PS4_SYSV_ABI wrap(Args... args) {
|
||||||
return func(args...);
|
if constexpr (std::is_same_v<ReturnType, void>) {
|
||||||
|
SwapTcb();
|
||||||
|
func(args...);
|
||||||
|
SwapTcb();
|
||||||
|
} else {
|
||||||
|
SwapTcb();
|
||||||
|
auto ret = func(args...);
|
||||||
|
SwapTcb();
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user