From 216bec15f6be4b3fa8fbec671fe9316e34f6b9c8 Mon Sep 17 00:00:00 2001 From: gibbed Date: Sun, 25 Nov 2018 09:56:22 -0600 Subject: [PATCH 1/6] [Kernel] Stub XamQueryLiveHiveW. --- src/xenia/kernel/xam/xam_info.cc | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/xenia/kernel/xam/xam_info.cc b/src/xenia/kernel/xam/xam_info.cc index fd722a68c..f0af2f7b7 100644 --- a/src/xenia/kernel/xam/xam_info.cc +++ b/src/xenia/kernel/xam/xam_info.cc @@ -420,6 +420,12 @@ dword_result_t XamGetPrivateEnumStructureFromHandle(unknown_t unk1, } DECLARE_XAM_EXPORT1(XamGetPrivateEnumStructureFromHandle, kNone, kStub); +dword_result_t XamQueryLiveHiveW(lpwstring_t name, lpvoid_t out_buf, + dword_t out_size, dword_t type /* guess */) { + return X_STATUS_INVALID_PARAMETER_1; +} +DECLARE_XAM_EXPORT1(XamQueryLiveHiveW, kNone, kStub); + void RegisterInfoExports(xe::cpu::ExportResolver* export_resolver, KernelState* kernel_state) {} From 64403d5dc61b7841fd6b40257107df5b5d3feffd Mon Sep 17 00:00:00 2001 From: gibbed Date: Sun, 25 Nov 2018 09:58:03 -0600 Subject: [PATCH 2/6] [Kernel] Don't directly call RtlNtStatusToDosError export. --- src/xenia/kernel/xam/xam_net.cc | 18 +++++++++--------- src/xenia/kernel/xboxkrnl/xboxkrnl_error.cc | 6 +++++- src/xenia/kernel/xboxkrnl/xboxkrnl_error.h | 2 +- 3 files changed, 15 insertions(+), 11 deletions(-) diff --git a/src/xenia/kernel/xam/xam_net.cc b/src/xenia/kernel/xam/xam_net.cc index f64637133..d0a3d70c3 100644 --- a/src/xenia/kernel/xam/xam_net.cc +++ b/src/xenia/kernel/xam/xam_net.cc @@ -356,7 +356,7 @@ dword_result_t NetDll_WSAWaitForMultipleEvents(dword_t num_events, } while (result == X_STATUS_ALERTED); if (XFAILED(result)) { - uint32_t error = xboxkrnl::RtlNtStatusToDosError(result); + uint32_t error = xboxkrnl::xeRtlNtStatusToDosError(result); XThread::SetLastError(error); return ~0u; } @@ -375,7 +375,7 @@ DECLARE_XAM_EXPORT1(NetDll_WSACreateEvent, kNetworking, kImplemented); dword_result_t NetDll_WSACloseEvent(dword_t event_handle) { X_STATUS result = kernel_state()->object_table()->ReleaseHandle(event_handle); if (XFAILED(result)) { - uint32_t error = xboxkrnl::RtlNtStatusToDosError(result); + uint32_t error = xboxkrnl::xeRtlNtStatusToDosError(result); XThread::SetLastError(error); return 0; } @@ -386,7 +386,7 @@ DECLARE_XAM_EXPORT1(NetDll_WSACloseEvent, kNetworking, kImplemented); dword_result_t NetDll_WSAResetEvent(dword_t event_handle) { X_STATUS result = xboxkrnl::xeNtClearEvent(event_handle); if (XFAILED(result)) { - uint32_t error = xboxkrnl::RtlNtStatusToDosError(result); + uint32_t error = xboxkrnl::xeRtlNtStatusToDosError(result); XThread::SetLastError(error); return 0; } @@ -397,7 +397,7 @@ DECLARE_XAM_EXPORT1(NetDll_WSAResetEvent, kNetworking, kImplemented); dword_result_t NetDll_WSASetEvent(dword_t event_handle) { X_STATUS result = xboxkrnl::xeNtSetEvent(event_handle, nullptr); if (XFAILED(result)) { - uint32_t error = xboxkrnl::RtlNtStatusToDosError(result); + uint32_t error = xboxkrnl::xeRtlNtStatusToDosError(result); XThread::SetLastError(error); return 0; } @@ -567,7 +567,7 @@ dword_result_t NetDll_socket(dword_t caller, dword_t af, dword_t type, if (XFAILED(result)) { socket->Release(); - uint32_t error = xboxkrnl::RtlNtStatusToDosError(result); + uint32_t error = xboxkrnl::xeRtlNtStatusToDosError(result); XThread::SetLastError(error); return -1; } @@ -643,7 +643,7 @@ dword_result_t NetDll_ioctlsocket(dword_t caller, dword_t socket_handle, X_STATUS status = socket->IOControl(cmd, arg_ptr); if (XFAILED(status)) { - XThread::SetLastError(xboxkrnl::RtlNtStatusToDosError(status)); + XThread::SetLastError(xboxkrnl::xeRtlNtStatusToDosError(status)); return -1; } @@ -665,7 +665,7 @@ dword_result_t NetDll_bind(dword_t caller, dword_t socket_handle, N_XSOCKADDR_IN native_name(name); X_STATUS status = socket->Bind(&native_name, namelen); if (XFAILED(status)) { - XThread::SetLastError(xboxkrnl::RtlNtStatusToDosError(status)); + XThread::SetLastError(xboxkrnl::xeRtlNtStatusToDosError(status)); return -1; } @@ -686,7 +686,7 @@ dword_result_t NetDll_connect(dword_t caller, dword_t socket_handle, N_XSOCKADDR native_name(name); X_STATUS status = socket->Connect(&native_name, namelen); if (XFAILED(status)) { - XThread::SetLastError(xboxkrnl::RtlNtStatusToDosError(status)); + XThread::SetLastError(xboxkrnl::xeRtlNtStatusToDosError(status)); return -1; } @@ -706,7 +706,7 @@ dword_result_t NetDll_listen(dword_t caller, dword_t socket_handle, X_STATUS status = socket->Listen(backlog); if (XFAILED(status)) { - XThread::SetLastError(xboxkrnl::RtlNtStatusToDosError(status)); + XThread::SetLastError(xboxkrnl::xeRtlNtStatusToDosError(status)); return -1; } diff --git a/src/xenia/kernel/xboxkrnl/xboxkrnl_error.cc b/src/xenia/kernel/xboxkrnl/xboxkrnl_error.cc index 676dcfea0..114111624 100644 --- a/src/xenia/kernel/xboxkrnl/xboxkrnl_error.cc +++ b/src/xenia/kernel/xboxkrnl/xboxkrnl_error.cc @@ -971,7 +971,7 @@ const error_lookup_table error_tables[] = { }; #undef MAKE_ENTRY -dword_result_t RtlNtStatusToDosError(dword_t source_status) { +uint32_t xeRtlNtStatusToDosError(uint32_t source_status) { uint32_t status = source_status; if (!status || (status & 0x20000000)) { return status; @@ -1010,6 +1010,10 @@ dword_result_t RtlNtStatusToDosError(dword_t source_status) { XELOGE("RtlNtStatusToDosError lookup NOT IMPLEMENTED"); return 317; // ERROR_MR_MID_NOT_FOUND } + +dword_result_t RtlNtStatusToDosError(dword_t source_status) { + return xeRtlNtStatusToDosError(source_status); +} DECLARE_XBOXKRNL_EXPORT3(RtlNtStatusToDosError, kNone, kImportant, kHighFrequency, kLogResult); diff --git a/src/xenia/kernel/xboxkrnl/xboxkrnl_error.h b/src/xenia/kernel/xboxkrnl/xboxkrnl_error.h index 0d0a8be19..9cd5240fc 100644 --- a/src/xenia/kernel/xboxkrnl/xboxkrnl_error.h +++ b/src/xenia/kernel/xboxkrnl/xboxkrnl_error.h @@ -17,7 +17,7 @@ namespace xe { namespace kernel { namespace xboxkrnl { -dword_result_t RtlNtStatusToDosError(dword_t source_status); +uint32_t xeRtlNtStatusToDosError(uint32_t source_status); } // namespace xboxkrnl } // namespace kernel From 70b07712b2104f13d94c928ec5b283424a3160a4 Mon Sep 17 00:00:00 2001 From: gibbed Date: Sun, 25 Nov 2018 10:01:22 -0600 Subject: [PATCH 3/6] [Kernel] Research on C++ exceptions. --- src/xenia/kernel/xboxkrnl/xboxkrnl_debug.cc | 126 ++++++++++++++------ 1 file changed, 89 insertions(+), 37 deletions(-) diff --git a/src/xenia/kernel/xboxkrnl/xboxkrnl_debug.cc b/src/xenia/kernel/xboxkrnl/xboxkrnl_debug.cc index 4753ca2c0..994c55f57 100644 --- a/src/xenia/kernel/xboxkrnl/xboxkrnl_debug.cc +++ b/src/xenia/kernel/xboxkrnl/xboxkrnl_debug.cc @@ -31,49 +31,101 @@ typedef struct { } X_THREADNAME_INFO; static_assert_size(X_THREADNAME_INFO, 0x10); -void RtlRaiseException(pointer_t record) { - if (record->exception_code == 0x406D1388) { - // SetThreadName. FFS. - // https://msdn.microsoft.com/en-us/library/xcb2z8hs.aspx +void HandleSetThreadName(pointer_t record) { + // SetThreadName. FFS. + // https://msdn.microsoft.com/en-us/library/xcb2z8hs.aspx - // TODO(benvanik): check record->number_parameters to make sure it's a - // correct size. - auto thread_info = - reinterpret_cast(&record->exception_information[0]); + // TODO(benvanik): check record->number_parameters to make sure it's a + // correct size. + auto thread_info = + reinterpret_cast(&record->exception_information[0]); - assert_true(thread_info->type == 0x1000); + assert_true(thread_info->type == 0x1000); - if (!thread_info->name_ptr) { - XELOGD("SetThreadName called with null name_ptr"); - return; - } - - auto name = - kernel_memory()->TranslateVirtual(thread_info->name_ptr); - - object_ref thread; - if (thread_info->thread_id == -1) { - // Current thread. - thread = retain_object(XThread::GetCurrentThread()); - } else { - // Lookup thread by ID. - thread = kernel_state()->GetThreadByID(thread_info->thread_id); - } - - if (thread) { - XELOGD("SetThreadName(%d, %s)", thread->thread_id(), name); - thread->set_name(name); - } - - // TODO(benvanik): unwinding required here? + if (!thread_info->name_ptr) { + XELOGD("SetThreadName called with null name_ptr"); return; } - if (record->exception_code == 0xE06D7363) { - // C++ exception. - // https://blogs.msdn.com/b/oldnewthing/archive/2010/07/30/10044061.aspx - xe::debugging::Break(); - return; + auto name = + kernel_memory()->TranslateVirtual(thread_info->name_ptr); + + object_ref thread; + if (thread_info->thread_id == -1) { + // Current thread. + thread = retain_object(XThread::GetCurrentThread()); + } else { + // Lookup thread by ID. + thread = kernel_state()->GetThreadByID(thread_info->thread_id); + } + + if (thread) { + XELOGD("SetThreadName(%d, %s)", thread->thread_id(), name); + thread->set_name(name); + } + + // TODO(benvanik): unwinding required here? +} + +typedef struct { + xe::be mdisp; + xe::be pdisp; + xe::be vdisp; +} x_PMD; + +typedef struct { + xe::be properties; + xe::be type_ptr; + x_PMD this_displacement; + xe::be size_or_offset; + xe::be copy_function_ptr; +} x_s__CatchableType; + +typedef struct { + xe::be number_catchable_types; + xe::be catchable_type_ptrs[1]; +} x_s__CatchableTypeArray; + +typedef struct { + xe::be attributes; + xe::be unwind_ptr; + xe::be forward_compat_ptr; + xe::be catchable_type_array_ptr; +} x_s__ThrowInfo; + +void HandleCppException(pointer_t record) { + // C++ exception. + // https://blogs.msdn.com/b/oldnewthing/archive/2010/07/30/10044061.aspx + // http://www.drdobbs.com/visual-c-exception-handling-instrumentat/184416600 + // http://www.openrce.org/articles/full_view/21 + + assert_true(record->number_parameters == 3); + assert_true(record->exception_information[0] == 0x19930520); + + auto thrown_ptr = record->exception_information[1]; + auto thrown = kernel_memory()->TranslateVirtual(thrown_ptr); + auto vftable_ptr = *reinterpret_cast*>(thrown); + + auto throw_info_ptr = record->exception_information[2]; + auto throw_info = + kernel_memory()->TranslateVirtual(throw_info_ptr); + auto catchable_types = + kernel_memory()->TranslateVirtual( + throw_info->catchable_type_array_ptr); + + xe::debugging::Break(); +} + +void RtlRaiseException(pointer_t record) { + switch (record->exception_code) { + case 0x406D1388: { + HandleSetThreadName(record); + return; + } + case 0xE06D7363: { + HandleCppException(record); + return; + } } // TODO(benvanik): unwinding. From 894034a9b0cb5d039fd3f8e80a7216132779b57a Mon Sep 17 00:00:00 2001 From: gibbed Date: Sun, 25 Nov 2018 10:02:29 -0600 Subject: [PATCH 4/6] [Kernel] Tag RtlMultiByteToUnicodeN, RtlUnicodeToMultiByteN as high frequency. --- src/xenia/kernel/xboxkrnl/xboxkrnl_rtl.cc | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/xenia/kernel/xboxkrnl/xboxkrnl_rtl.cc b/src/xenia/kernel/xboxkrnl/xboxkrnl_rtl.cc index 94c36fbc7..2b3ab5f67 100644 --- a/src/xenia/kernel/xboxkrnl/xboxkrnl_rtl.cc +++ b/src/xenia/kernel/xboxkrnl/xboxkrnl_rtl.cc @@ -286,7 +286,8 @@ dword_result_t RtlMultiByteToUnicodeN(lpword_t destination_ptr, return 0; } -DECLARE_XBOXKRNL_EXPORT2(RtlMultiByteToUnicodeN, kNone, kImplemented, kSketchy); +DECLARE_XBOXKRNL_EXPORT3(RtlMultiByteToUnicodeN, kNone, kImplemented, + kHighFrequency, kSketchy); // https://msdn.microsoft.com/en-us/library/ff553261 dword_result_t RtlUnicodeToMultiByteN(pointer_t destination_ptr, @@ -308,7 +309,8 @@ dword_result_t RtlUnicodeToMultiByteN(pointer_t destination_ptr, return 0; } -DECLARE_XBOXKRNL_EXPORT2(RtlUnicodeToMultiByteN, kNone, kImplemented, kSketchy); +DECLARE_XBOXKRNL_EXPORT3(RtlUnicodeToMultiByteN, kNone, kImplemented, + kHighFrequency, kSketchy); pointer_result_t RtlImageXexHeaderField(pointer_t xex_header, dword_t field_dword) { From e91e1c88240c22f870efa782df2a0db0fab33d4a Mon Sep 17 00:00:00 2001 From: gibbed Date: Sun, 25 Nov 2018 10:19:40 -0600 Subject: [PATCH 5/6] [Kernel] Tag XAudioGetVoiceCategoryVolume as high frequency. --- src/xenia/kernel/xboxkrnl/xboxkrnl_audio.cc | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/xenia/kernel/xboxkrnl/xboxkrnl_audio.cc b/src/xenia/kernel/xboxkrnl/xboxkrnl_audio.cc index 3c3c1e910..d9c861211 100644 --- a/src/xenia/kernel/xboxkrnl/xboxkrnl_audio.cc +++ b/src/xenia/kernel/xboxkrnl/xboxkrnl_audio.cc @@ -45,7 +45,8 @@ dword_result_t XAudioGetVoiceCategoryVolume(dword_t unk, lpfloat_t out_ptr) { return X_ERROR_SUCCESS; } -DECLARE_XBOXKRNL_EXPORT1(XAudioGetVoiceCategoryVolume, kAudio, kStub); +DECLARE_XBOXKRNL_EXPORT2(XAudioGetVoiceCategoryVolume, kAudio, kStub, + kHighFrequency); dword_result_t XAudioEnableDucker(dword_t unk) { return X_ERROR_SUCCESS; } DECLARE_XBOXKRNL_EXPORT1(XAudioEnableDucker, kAudio, kStub); From bd45a5defd5daa6283ded3e9a475f25d5e693812 Mon Sep 17 00:00:00 2001 From: gibbed Date: Sun, 25 Nov 2018 11:06:57 -0600 Subject: [PATCH 6/6] [Kernel] Fix timeout in NtWaitForMultipleObjectsEx. --- .../kernel/xboxkrnl/xboxkrnl_threading.cc | 24 +++++++++---------- src/xenia/kernel/xevent.h | 1 + src/xenia/kernel/xsemaphore.h | 1 + 3 files changed, 14 insertions(+), 12 deletions(-) diff --git a/src/xenia/kernel/xboxkrnl/xboxkrnl_threading.cc b/src/xenia/kernel/xboxkrnl/xboxkrnl_threading.cc index 09d7e5439..40307c6f6 100644 --- a/src/xenia/kernel/xboxkrnl/xboxkrnl_threading.cc +++ b/src/xenia/kernel/xboxkrnl/xboxkrnl_threading.cc @@ -736,7 +736,7 @@ DECLARE_XBOXKRNL_EXPORT1(NtCancelTimer, kThreading, kImplemented); uint32_t xeKeWaitForSingleObject(void* object_ptr, uint32_t wait_reason, uint32_t processor_mode, uint32_t alertable, - uint64_t* timeout) { + uint64_t* timeout_ptr) { auto object = XObject::GetNativeObject(kernel_state(), object_ptr); if (!object) { @@ -746,7 +746,7 @@ uint32_t xeKeWaitForSingleObject(void* object_ptr, uint32_t wait_reason, } X_STATUS result = - object->Wait(wait_reason, processor_mode, alertable, timeout); + object->Wait(wait_reason, processor_mode, alertable, timeout_ptr); return result; } @@ -756,7 +756,7 @@ dword_result_t KeWaitForSingleObject(lpvoid_t object_ptr, dword_t wait_reason, lpqword_t timeout_ptr) { uint64_t timeout = timeout_ptr ? static_cast(*timeout_ptr) : 0u; return xeKeWaitForSingleObject(object_ptr, wait_reason, processor_mode, - alertable, &timeout); + alertable, timeout_ptr ? &timeout : nullptr); } DECLARE_XBOXKRNL_EXPORT3(KeWaitForSingleObject, kThreading, kImplemented, kBlocking, kHighFrequency); @@ -819,7 +819,6 @@ uint32_t xeNtWaitForMultipleObjectsEx(uint32_t count, xe::be* handles, uint32_t alertable, uint64_t* timeout_ptr) { assert_true(wait_type <= 1); - X_STATUS result = X_STATUS_SUCCESS; std::vector> objects; for (uint32_t n = 0; n < count; n++) { @@ -832,11 +831,9 @@ uint32_t xeNtWaitForMultipleObjectsEx(uint32_t count, xe::be* handles, objects.push_back(std::move(object)); } - result = - XObject::WaitMultiple(count, reinterpret_cast(objects.data()), - wait_type, 6, wait_mode, alertable, timeout_ptr); - - return result; + return XObject::WaitMultiple(count, + reinterpret_cast(objects.data()), + wait_type, 6, wait_mode, alertable, timeout_ptr); } dword_result_t NtWaitForMultipleObjectsEx(dword_t count, lpdword_t handles, @@ -845,7 +842,8 @@ dword_result_t NtWaitForMultipleObjectsEx(dword_t count, lpdword_t handles, lpqword_t timeout_ptr) { uint64_t timeout = timeout_ptr ? static_cast(*timeout_ptr) : 0u; return xeNtWaitForMultipleObjectsEx(count, handles, wait_type, wait_mode, - alertable, &timeout); + alertable, + timeout_ptr ? &timeout : nullptr); } DECLARE_XBOXKRNL_EXPORT3(NtWaitForMultipleObjectsEx, kThreading, kImplemented, kBlocking, kHighFrequency); @@ -1132,6 +1130,7 @@ struct X_ERWLOCK { X_KSEMAPHORE reader_semaphore; // 0x20 uint32_t spin_lock; // 0x34 }; +static_assert_size(X_ERWLOCK, 0x38); void ExInitializeReadWriteLock(pointer_t lock_ptr) { lock_ptr->lock_count = -1; @@ -1140,6 +1139,7 @@ void ExInitializeReadWriteLock(pointer_t lock_ptr) { lock_ptr->readers_entry_count = 0; KeInitializeEvent(&lock_ptr->writer_event, 1, 0); KeInitializeSemaphore(&lock_ptr->reader_semaphore, 0, 0x7FFFFFFF); + lock_ptr->spin_lock = 0; } DECLARE_XBOXKRNL_EXPORT1(ExInitializeReadWriteLock, kThreading, kImplemented); @@ -1155,8 +1155,8 @@ void ExAcquireReadWriteLockExclusive(pointer_t lock_ptr) { lock_ptr->writers_waiting_count++; xeKeWaitForSingleObject(&lock_ptr->writer_event, 0, 0, 0, nullptr); } -DECLARE_XBOXKRNL_EXPORT4(ExAcquireReadWriteLockExclusive, kThreading, - kImplemented, kBlocking, kHighFrequency, kSketchy); +DECLARE_XBOXKRNL_EXPORT3(ExAcquireReadWriteLockExclusive, kThreading, + kImplemented, kBlocking, kSketchy); void ExReleaseReadWriteLock(pointer_t lock_ptr) { auto old_irql = xeKeKfAcquireSpinLock(&lock_ptr->spin_lock); diff --git a/src/xenia/kernel/xevent.h b/src/xenia/kernel/xevent.h index 6502f77f1..95ea8613f 100644 --- a/src/xenia/kernel/xevent.h +++ b/src/xenia/kernel/xevent.h @@ -21,6 +21,7 @@ namespace kernel { struct X_KEVENT { X_DISPATCH_HEADER header; }; +static_assert_size(X_KEVENT, 0x10); class XEvent : public XObject { public: diff --git a/src/xenia/kernel/xsemaphore.h b/src/xenia/kernel/xsemaphore.h index 1b0bc5804..42ae7ee26 100644 --- a/src/xenia/kernel/xsemaphore.h +++ b/src/xenia/kernel/xsemaphore.h @@ -21,6 +21,7 @@ struct X_KSEMAPHORE { X_DISPATCH_HEADER header; xe::be limit; }; +static_assert_size(X_KSEMAPHORE, 0x14); class XSemaphore : public XObject { public: