ARM64EC: Rely on syscall export sorting for deriving their IDs

Rather than relying on wine-specific alphabetical behaviour, that
has since been changed. Rely on their addresses being sorted which
is more stable behaviour also present in Windows.
This commit is contained in:
Billy Laws committed 2025-07-10 16:00:07 +01:00
1 parent d8a4d03501
commit 793e3adbb4
1 file changed
+30 -12
+30 -12
View File
@@ -204,23 +204,41 @@ 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);
const auto* FunctionTable = reinterpret_cast<uint32_t*>(NtDllBase + Exports->AddressOfFunctions);
const auto* OrdinalTable = reinterpret_cast<uint16_t*>(NtDllBase + Exports->AddressOfNameOrdinals);
struct SyscallEntry {
const char* Name;
uint32_t RVA;
// 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;
bool operator<(const SyscallEntry& Other) const {
return RVA < Other.RVA;
}
};
// Cannot use any syscalls at this stage, so rely on a stack-allocated array
std::array<SyscallEntry, 0x200> SyscallTable;
auto SyscallTableEnd = SyscallTable.begin();
// Windows/Wine orders syscalls in memory by their ID, 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.
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;
}
*SyscallTableEnd++ = {Name, FunctionTable[OrdinalTable[Idx]]};
}
}
CurSyscallId++;
// Sort such that index 0 is now syscall 0, etc
std::sort(SyscallTable.begin(), SyscallTableEnd);
for (auto it = SyscallTable.begin(); it != SyscallTableEnd; it++) {
uint32_t CurSyscallId = static_cast<uint32_t>(std::distance(SyscallTable.begin(), it));
if (strcmp(it->Name, "NtContinue") == 0) {
WineNtContinueSyscallId = CurSyscallId;
} else if (strcmp(it->Name, "NtAllocateVirtualMemory") == 0) {
WineNtAllocateVirtualMemorySyscallId = CurSyscallId;
} else if (strcmp(it->Name, "NtProtectVirtualMemory") == 0) {
WineNtProtectVirtualMemorySyscallId = CurSyscallId;
}
}
}