MCPcopy Create free account
hub / github.com/FEX-Emu/FEX / ParseWineSyscallNumbers

Function ParseWineSyscallNumbers

Source/Windows/ARM64EC/Module.cpp:209–250  ·  view source on GitHub ↗

Fills in the syscall numbers necessary to call *Native variants of syscalls from FEX under wine.

Source from the content-addressed store, hash-verified

207
208// Fills in the syscall numbers necessary to call *Native variants of syscalls from FEX under wine.
209void ParseWineSyscallNumbers(HMODULE NtDll) {
210 ULONG Size;
211 const auto* Exports = reinterpret_cast<IMAGE_EXPORT_DIRECTORY*>(RtlImageDirectoryEntryToData(NtDll, true, IMAGE_DIRECTORY_ENTRY_EXPORT, &Size));
212 const auto* NameTable = reinterpret_cast<uint32_t*>(NtDllBase + Exports->AddressOfNames);
213 const auto* FunctionTable = reinterpret_cast<uint32_t*>(NtDllBase + Exports->AddressOfFunctions);
214 const auto* OrdinalTable = reinterpret_cast<uint16_t*>(NtDllBase + Exports->AddressOfNameOrdinals);
215 struct SyscallEntry {
216 const char* Name;
217 uint32_t RVA;
218
219 bool operator<(const SyscallEntry& Other) const {
220 return RVA < Other.RVA;
221 }
222 };
223
224 // Cannot use any syscalls at this stage, so rely on a stack-allocated array
225 std::array<SyscallEntry, 0x200> SyscallTable;
226 auto SyscallTableEnd = SyscallTable.begin();
227
228 // Windows/Wine orders syscalls in memory by their ID, take advantage of that to find the syscall indices for those
229 // which we need to manually issue. Note that all functions starting with Nt besides NtGetTickCount are syscalls.
230 for (uint32_t Idx = 0; Idx < Exports->NumberOfNames; Idx++) {
231 const char* Name = reinterpret_cast<const char*>(NtDllBase + NameTable[Idx]);
232 if (Name[0] == 'N' && Name[1] == 't' && strcmp(Name, "NtGetTickCount") != 0) {
233 *SyscallTableEnd++ = {Name, FunctionTable[OrdinalTable[Idx]]};
234 }
235 }
236
237 // Sort such that index 0 is now syscall 0, etc
238 std::sort(SyscallTable.begin(), SyscallTableEnd);
239
240 for (auto it = SyscallTable.begin(); it != SyscallTableEnd; it++) {
241 uint32_t CurSyscallId = static_cast<uint32_t>(std::distance(SyscallTable.begin(), it));
242 if (strcmp(it->Name, "NtContinue") == 0) {
243 WineNtContinueSyscallId = CurSyscallId;
244 } else if (strcmp(it->Name, "NtAllocateVirtualMemory") == 0) {
245 WineNtAllocateVirtualMemorySyscallId = CurSyscallId;
246 } else if (strcmp(it->Name, "NtProtectVirtualMemory") == 0) {
247 WineNtProtectVirtualMemorySyscallId = CurSyscallId;
248 }
249 }
250}
251
252// Syscall thunks may have been patched before FEX has loaded, the default call checker installed by ntdll into FEX will
253// try to invoke the JIT when calling such patched syscalls but this obviously doesn't work before FEX is initalised.

Callers 1

InitSyscallsFunction · 0.85

Calls 1

beginMethod · 0.45

Tested by

no test coverage detected