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.