mirror of
https://github.com/FEX-Emu/FEX.git
synced 2026-10-14 07:00:43 +02:00
ARM64EC: Dynamically determine syscall numbers under wine
Takes advantage of the consistent alphabetical syscall ordering that wine follows.
This commit is contained in:
1 parent
e902ad5278
commit
38acd9e18c
1 file changed
+32
-5
@@ -69,10 +69,9 @@ uint32_t NtDllRedirectionLUTSize;
|
||||
|
||||
// Wine doesn't support issuing direct system calls with SVC, and unlike Windows it doesn't have a 'stable' syscall number for NtContinue
|
||||
void* WineSyscallDispatcher;
|
||||
// TODO: this really shouldn't be hardcoded, once wine gains proper syscall thunks this can be dropped.
|
||||
uint64_t WineNtContinueSyscallId = 0x1a;
|
||||
uint64_t WineNtAllocateVirtualMemorySyscallId = 0xb;
|
||||
uint64_t WineNtProtectVirtualMemorySyscallId = 0x76;
|
||||
uint64_t WineNtContinueSyscallId;
|
||||
uint64_t WineNtAllocateVirtualMemorySyscallId;
|
||||
uint64_t WineNtProtectVirtualMemorySyscallId;
|
||||
|
||||
NTSTATUS NtContinueNative(ARM64_NT_CONTEXT* NativeContext, BOOLEAN Alert);
|
||||
NTSTATUS NtAllocateVirtualMemoryNative(HANDLE, PVOID*, ULONG_PTR, SIZE_T*, ULONG, ULONG);
|
||||
@@ -151,7 +150,6 @@ bool IsDispatcherAddress(uint64_t Address) {
|
||||
|
||||
|
||||
void FillNtDllLUTs(HMODULE NtDll) {
|
||||
NtDllBase = reinterpret_cast<uintptr_t>(NtDll);
|
||||
ULONG Size;
|
||||
const auto* LoadConfig =
|
||||
reinterpret_cast<_IMAGE_LOAD_CONFIG_DIRECTORY64*>(RtlImageDirectoryEntryToData(NtDll, true, IMAGE_DIRECTORY_ENTRY_LOAD_CONFIG, &Size));
|
||||
@@ -196,6 +194,32 @@ void PatchCallChecker() {
|
||||
WriteModuleRVA(Module, CHPEMetadata->__os_arm64x_dispatch_icall_cfg, &CheckCall);
|
||||
}
|
||||
|
||||
// Fills in the syscall numbers necessary to call *Native variants of syscalls from FEX under wine.
|
||||
void ParseWineSyscallNumbers(HMODULE NtDll) {
|
||||
ULONG Size;
|
||||
const auto* Exports = reinterpret_cast<IMAGE_EXPORT_DIRECTORY*>(RtlImageDirectoryEntryToData(NtDll, true, IMAGE_DIRECTORY_ENTRY_EXPORT, &Size));
|
||||
const auto* NameTable = reinterpret_cast<uint32_t*>(NtDllBase + Exports->AddressOfNames);
|
||||
|
||||
// Wine orders syscalls alphabetically, take advantage of that to find the syscall indices for those which we need to
|
||||
// manually issue. Note that all functions starting with Nt besides NtGetTickCount are syscalls and the syscall ID must
|
||||
// be incremented by 1 for each.
|
||||
uint32_t CurSyscallId = 0;
|
||||
for (uint32_t Idx = 0; Idx < Exports->NumberOfNames; Idx++) {
|
||||
const char* Name = reinterpret_cast<const char*>(NtDllBase + NameTable[Idx]);
|
||||
if (Name[0] == 'N' && Name[1] == 't' && strcmp(Name, "NtGetTickCount") != 0) {
|
||||
if (strcmp(Name, "NtContinue") == 0) {
|
||||
WineNtContinueSyscallId = CurSyscallId;
|
||||
} else if (strcmp(Name, "NtAllocateVirtualMemory") == 0) {
|
||||
WineNtAllocateVirtualMemorySyscallId = CurSyscallId;
|
||||
} else if (strcmp(Name, "NtProtectVirtualMemory") == 0) {
|
||||
WineNtProtectVirtualMemorySyscallId = CurSyscallId;
|
||||
}
|
||||
|
||||
CurSyscallId++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Syscall thunks may have been patched before FEX has loaded, the default call checker installed by ntdll into FEX will
|
||||
// try to invoke the JIT when calling such patched syscalls but this obviously doesn't work before FEX is initalised.
|
||||
// This function parses ntdll and sets up a custom call checker to prevent this, as such it must avoid using any syscall
|
||||
@@ -204,9 +228,12 @@ void InitSyscalls() {
|
||||
// The ntdll exports called by GetModuleHandle/GetProcAddress aren't known to be patched before JIT init by any current
|
||||
// software so are safe to call, but if that changes the loader structures in the PEB could be parsed manually.
|
||||
const auto NtDll = GetModuleHandle("ntdll.dll");
|
||||
NtDllBase = reinterpret_cast<uintptr_t>(NtDll);
|
||||
|
||||
const auto WineSyscallDispatcherPtr = reinterpret_cast<void**>(GetProcAddress(NtDll, "__wine_syscall_dispatcher"));
|
||||
if (WineSyscallDispatcherPtr) {
|
||||
WineSyscallDispatcher = *WineSyscallDispatcherPtr;
|
||||
ParseWineSyscallNumbers(NtDll);
|
||||
}
|
||||
|
||||
FillNtDllLUTs(NtDll);
|
||||
|
||||
Reference in new issue
Block a user