diff options
| author | gibbed <rick@gibbed.us> | 2018-11-25 10:01:22 -0600 |
|---|---|---|
| committer | gibbed <rick@gibbed.us> | 2018-11-25 10:01:22 -0600 |
| commit | 70b07712b2104f13d94c928ec5b283424a3160a4 (patch) | |
| tree | 73dd436e4a2680ef92855844312952cd05885409 | |
| parent | 64403d5dc61b7841fd6b40257107df5b5d3feffd (diff) | |
[Kernel] Research on C++ exceptions.
| -rw-r--r-- | src/xenia/kernel/xboxkrnl/xboxkrnl_debug.cc | 122 |
1 files changed, 87 insertions, 35 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<X_EXCEPTION_RECORD> record) { - if (record->exception_code == 0x406D1388) { - // 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<X_THREADNAME_INFO*>(&record->exception_information[0]); +void HandleSetThreadName(pointer_t<X_EXCEPTION_RECORD> record) { + // SetThreadName. FFS. + // https://msdn.microsoft.com/en-us/library/xcb2z8hs.aspx - assert_true(thread_info->type == 0x1000); + // TODO(benvanik): check record->number_parameters to make sure it's a + // correct size. + auto thread_info = + reinterpret_cast<X_THREADNAME_INFO*>(&record->exception_information[0]); - if (!thread_info->name_ptr) { - XELOGD("SetThreadName called with null name_ptr"); - return; - } + assert_true(thread_info->type == 0x1000); - auto name = - kernel_memory()->TranslateVirtual<const char*>(thread_info->name_ptr); + if (!thread_info->name_ptr) { + XELOGD("SetThreadName called with null name_ptr"); + return; + } - object_ref<XThread> 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); - } + auto name = + kernel_memory()->TranslateVirtual<const char*>(thread_info->name_ptr); - if (thread) { - XELOGD("SetThreadName(%d, %s)", thread->thread_id(), name); - thread->set_name(name); - } + object_ref<XThread> 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); + } - // TODO(benvanik): unwinding required here? - return; + if (thread) { + XELOGD("SetThreadName(%d, %s)", thread->thread_id(), name); + thread->set_name(name); } - if (record->exception_code == 0xE06D7363) { - // C++ exception. - // https://blogs.msdn.com/b/oldnewthing/archive/2010/07/30/10044061.aspx - xe::debugging::Break(); - return; + // TODO(benvanik): unwinding required here? +} + +typedef struct { + xe::be<int32_t> mdisp; + xe::be<int32_t> pdisp; + xe::be<int32_t> vdisp; +} x_PMD; + +typedef struct { + xe::be<uint32_t> properties; + xe::be<uint32_t> type_ptr; + x_PMD this_displacement; + xe::be<int32_t> size_or_offset; + xe::be<uint32_t> copy_function_ptr; +} x_s__CatchableType; + +typedef struct { + xe::be<int32_t> number_catchable_types; + xe::be<uint32_t> catchable_type_ptrs[1]; +} x_s__CatchableTypeArray; + +typedef struct { + xe::be<uint32_t> attributes; + xe::be<uint32_t> unwind_ptr; + xe::be<uint32_t> forward_compat_ptr; + xe::be<uint32_t> catchable_type_array_ptr; +} x_s__ThrowInfo; + +void HandleCppException(pointer_t<X_EXCEPTION_RECORD> 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<xe::be<uint32_t>*>(thrown); + + auto throw_info_ptr = record->exception_information[2]; + auto throw_info = + kernel_memory()->TranslateVirtual<x_s__ThrowInfo*>(throw_info_ptr); + auto catchable_types = + kernel_memory()->TranslateVirtual<x_s__CatchableTypeArray*>( + throw_info->catchable_type_array_ptr); + + xe::debugging::Break(); +} + +void RtlRaiseException(pointer_t<X_EXCEPTION_RECORD> record) { + switch (record->exception_code) { + case 0x406D1388: { + HandleSetThreadName(record); + return; + } + case 0xE06D7363: { + HandleCppException(record); + return; + } } // TODO(benvanik): unwinding. |
