"Fix" debug console, we were checking the cvar before any cvars were loaded, and the condition it checks in AttachConsole is somehow always false
Remove dead #if 0'd code in math.h On amd64, page_size == 4096 constant, on amd64 w/ win32, allocation_granularity == 65536. These values for x86 windows havent changed over the last 20 years so this is probably safe and gives a modest code size reduction Enable XE_USE_KUSER_SHARED. This sources host time from KUSER_SHARED instead of from QueryPerformanceCounter, which is far faster, but only has a granularity of 100 nanoseconds. In some games seemingly random crashes were happening that were hard to trace because the faulting thread was actually not the one that was misbehaving, another threads stack was underflowing into the faulting thread. Added a bunch of code to synchronize the guest stack and host stack so that if a guest longjmps the host's stack will be adjusted. Changes were also made to allow the guest to call into a piece of an existing x64 function. This synchronization might have a slight performance impact on lower end cpus, to disable it set enable_host_guest_stack_synchronization to false. It is possible it may have introduced regressions, but i dont know of any yet So far, i know the synchronization change fixes the "hub crash" in super sonic and allows the game "london 2012" to go ingame. Removed emit_useless_fpscr_updates, not emitting these updates breaks the raiden game MapGuestAddressToMachineCode now returns nullptr if no address was found, instead of the start of the function add Processor::LookupModule Add Backend::DeinitializeBackendContext Use WriteRegisterRangeFromRing_WithKnownBound<0, 0xFFFF> in WriteRegisterRangeFromRing for inlining (previously regressed on performance of ExecutePacketType0) add notes about flags that trap in XamInputGetCapabilities 0 == 3 in XamInputGetCapabilities Name arg 2 of XamInputSetState PrefetchW in critical section kernel funcs if available & doing cmpxchg Add terminated field to X_KTHREAD, set it on termination Expanded the logic of NtResumeThread/NtSuspendThread to include checking the type of the handle (in release, LookupObject doesnt seem to do anything with the type) and returning X_STATUS_OBJECT_TYPE_MISMATCH if invalid. Do termination check in NtSuspendThread. Add basic host exception messagebox, need to flesh it out more (maybe use the new stack tracking stuff if on guest thrd?) Add rdrand patching hack, mostly affects users with nvidia cards who have many threads on zen Use page_size_shift in more places Once again disable precompilation! Raiden is mostly weird ppc asm which probably breaks the precompilation. The code is still useful for running the compiler over the whole of an xex in debug to test for issues "Fix" debug console, we were checking the cvar before any cvars were loaded, and the condition it checks in AttachConsole is somehow always false Remove dead #if 0'd code in math.h On amd64, page_size == 4096 constant, on amd64 w/ win32, allocation_granularity == 65536. These values for x86 windows havent changed over the last 20 years so this is probably safe and gives a modest code size reduction Enable XE_USE_KUSER_SHARED. This sources host time from KUSER_SHARED instead of from QueryPerformanceCounter, which is far faster, but only has a granularity of 100 nanoseconds. In some games seemingly random crashes were happening that were hard to trace because the faulting thread was actually not the one that was misbehaving, another threads stack was underflowing into the faulting thread. Added a bunch of code to synchronize the guest stack and host stack so that if a guest longjmps the host's stack will be adjusted. Changes were also made to allow the guest to call into a piece of an existing x64 function. This synchronization might have a slight performance impact on lower end cpus, to disable it set enable_host_guest_stack_synchronization to false. It is possible it may have introduced regressions, but i dont know of any yet So far, i know the synchronization change fixes the "hub crash" in super sonic and allows the game "london 2012" to go ingame. Removed emit_useless_fpscr_updates, not emitting these updates breaks the raiden game MapGuestAddressToMachineCode now returns nullptr if no address was found, instead of the start of the function add Processor::LookupModule Add Backend::DeinitializeBackendContext Use WriteRegisterRangeFromRing_WithKnownBound<0, 0xFFFF> in WriteRegisterRangeFromRing for inlining (previously regressed on performance of ExecutePacketType0) add notes about flags that trap in XamInputGetCapabilities 0 == 3 in XamInputGetCapabilities Name arg 2 of XamInputSetState PrefetchW in critical section kernel funcs if available & doing cmpxchg Add terminated field to X_KTHREAD, set it on termination Expanded the logic of NtResumeThread/NtSuspendThread to include checking the type of the handle (in release, LookupObject doesnt seem to do anything with the type) and returning X_STATUS_OBJECT_TYPE_MISMATCH if invalid. Do termination check in NtSuspendThread. Add basic host exception messagebox, need to flesh it out more (maybe use the new stack tracking stuff if on guest thrd?) Add rdrand patching hack, mostly affects users with nvidia cards who have many threads on zen Use page_size_shift in more places Once again disable precompilation! Raiden is mostly weird ppc asm which probably breaks the precompilation. The code is still useful for running the compiler over the whole of an xex in debug to test for issues
This commit is contained in:
@@ -19,11 +19,96 @@
|
||||
|
||||
DEFINE_bool(enable_console, false, "Open a console window with the main window",
|
||||
"General");
|
||||
#if XE_ARCH_AMD64 == 1
|
||||
DEFINE_bool(enable_rdrand_ntdll_patch, true,
|
||||
"Hot-patches ntdll at the start of the process to not use rdrand "
|
||||
"as part of the RNG for heap randomization. Can reduce CPU usage "
|
||||
"significantly, but is untested on all Windows versions.",
|
||||
"Win32");
|
||||
// begin ntdll hack
|
||||
#include <psapi.h>
|
||||
static bool g_didfailtowrite = false;
|
||||
static void write_process_memory(HANDLE process, uintptr_t offset,
|
||||
unsigned size, const unsigned char* bvals) {
|
||||
if (!WriteProcessMemory(process, (void*)offset, bvals, size, nullptr)) {
|
||||
if (!g_didfailtowrite) {
|
||||
MessageBoxA(nullptr, "Failed to write to process!", "Failed", MB_OK);
|
||||
g_didfailtowrite = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static const unsigned char pattern_cmp_processorfeature_28_[] = {
|
||||
0x80, 0x3C, 0x25, 0x90,
|
||||
0x02, 0xFE, 0x7F, 0x00}; // cmp byte ptr ds:7FFE0290h, 0
|
||||
static const unsigned char pattern_replacement[] = {
|
||||
0x48, 0x39, 0xe4, // cmp rsp, rsp = always Z
|
||||
0x0F, 0x1F, 0x44, 0x00, 0x00 // 5byte nop
|
||||
};
|
||||
static void patch_ntdll_instance(HANDLE process, uintptr_t ntdll_base) {
|
||||
MODULEINFO modinfo;
|
||||
|
||||
GetModuleInformation(process, (HMODULE)ntdll_base, &modinfo,
|
||||
sizeof(MODULEINFO));
|
||||
|
||||
std::vector<uintptr_t> possible_places{};
|
||||
|
||||
unsigned char* strt = (unsigned char*)modinfo.lpBaseOfDll;
|
||||
|
||||
for (unsigned i = 0; i < modinfo.SizeOfImage; ++i) {
|
||||
for (unsigned j = 0; j < sizeof(pattern_cmp_processorfeature_28_); ++j) {
|
||||
if (strt[i + j] != pattern_cmp_processorfeature_28_[j]) {
|
||||
goto miss;
|
||||
}
|
||||
}
|
||||
possible_places.push_back((uintptr_t)(&strt[i]));
|
||||
miss:;
|
||||
}
|
||||
|
||||
for (auto&& place : possible_places) {
|
||||
write_process_memory(process, place, sizeof(pattern_replacement),
|
||||
pattern_replacement);
|
||||
}
|
||||
}
|
||||
|
||||
static void do_ntdll_hack_this_process() {
|
||||
patch_ntdll_instance(GetCurrentProcess(),
|
||||
(uintptr_t)GetModuleHandleA("ntdll.dll"));
|
||||
}
|
||||
#endif
|
||||
// end ntdll hack
|
||||
LONG _UnhandledExceptionFilter(_EXCEPTION_POINTERS* ExceptionInfo) {
|
||||
PVOID exception_addr = ExceptionInfo->ExceptionRecord->ExceptionAddress;
|
||||
|
||||
DWORD64 last_stackpointer = ExceptionInfo->ContextRecord->Rsp;
|
||||
|
||||
DWORD64 last_rip = ExceptionInfo->ContextRecord->Rip;
|
||||
|
||||
DWORD except_code = ExceptionInfo->ExceptionRecord->ExceptionCode;
|
||||
|
||||
DWORD last_error = GetLastError();
|
||||
|
||||
NTSTATUS stat = __readgsdword(0x1250);
|
||||
|
||||
int last_errno_value = errno;
|
||||
|
||||
|
||||
|
||||
char except_message_buf[1024];
|
||||
|
||||
sprintf_s(except_message_buf,
|
||||
"Exception encountered!\nException address: %p\nStackpointer: "
|
||||
"%p\nInstruction pointer: %p\nExceptionCode: 0x%X\nLast Win32 "
|
||||
"Error: 0x%X\nLast NTSTATUS: 0x%X\nLast errno value: 0x%X\n",
|
||||
exception_addr, (void*)last_stackpointer, (void*)last_rip, except_code,
|
||||
last_error, stat, last_errno_value);
|
||||
MessageBoxA(nullptr, except_message_buf, "Unhandled Exception", MB_ICONERROR);
|
||||
return EXCEPTION_CONTINUE_SEARCH;
|
||||
}
|
||||
int WINAPI wWinMain(HINSTANCE hinstance, HINSTANCE hinstance_prev,
|
||||
LPWSTR command_line, int show_cmd) {
|
||||
int result;
|
||||
|
||||
SetUnhandledExceptionFilter(_UnhandledExceptionFilter);
|
||||
{
|
||||
xe::ui::Win32WindowedAppContext app_context(hinstance, show_cmd);
|
||||
// TODO(Triang3l): Initialize creates a window. Set DPI awareness via the
|
||||
@@ -40,13 +125,6 @@ int WINAPI wWinMain(HINSTANCE hinstance, HINSTANCE hinstance_prev,
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
// TODO(Triang3l): Rework this, need to initialize the console properly,
|
||||
// disable has_console_attached_ by default in windowed apps, and attach
|
||||
// only if needed.
|
||||
if (cvars::enable_console) {
|
||||
xe::AttachConsole();
|
||||
}
|
||||
|
||||
// Initialize COM on the UI thread with the apartment-threaded concurrency
|
||||
// model, so dialogs can be used.
|
||||
if (FAILED(CoInitializeEx(nullptr, COINIT_APARTMENTTHREADED))) {
|
||||
@@ -55,8 +133,22 @@ int WINAPI wWinMain(HINSTANCE hinstance, HINSTANCE hinstance_prev,
|
||||
|
||||
xe::InitializeWin32App(app->GetName());
|
||||
|
||||
result =
|
||||
app->OnInitialize() ? app_context.RunMainMessageLoop() : EXIT_FAILURE;
|
||||
if (app->OnInitialize()) {
|
||||
#if XE_ARCH_AMD64 == 1
|
||||
if (cvars::enable_rdrand_ntdll_patch) {
|
||||
do_ntdll_hack_this_process();
|
||||
}
|
||||
#endif
|
||||
// TODO(Triang3l): Rework this, need to initialize the console properly,
|
||||
// disable has_console_attached_ by default in windowed apps, and attach
|
||||
// only if needed.
|
||||
if (cvars::enable_console) {
|
||||
xe::AttachConsole();
|
||||
}
|
||||
result = app_context.RunMainMessageLoop();
|
||||
} else {
|
||||
result = EXIT_FAILURE;
|
||||
}
|
||||
|
||||
app->InvokeOnDestroy();
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user