/** ****************************************************************************** * Xenia : Xbox 360 Emulator Research Project * ****************************************************************************** * Copyright 2013 Ben Vanik. All rights reserved. * * Released under the BSD license - see LICENSE in the root for more details. * ****************************************************************************** */ #include "xenia/base/debugging.h" #include "xenia/base/logging.h" #include "xenia/kernel/kernel_state.h" #include "xenia/kernel/util/shim_utils.h" #include "xenia/kernel/xboxkrnl/xboxkrnl_private.h" #include "xenia/kernel/xthread.h" #include "xenia/xbox.h" namespace xe { namespace kernel { namespace xboxkrnl { void DbgBreakPoint() { xe::debugging::Break(); } DECLARE_XBOXKRNL_EXPORT2(DbgBreakPoint, kDebug, kStub, kImportant); // https://msdn.microsoft.com/en-us/library/xcb2z8hs.aspx typedef struct { xe::be type; xe::be name_ptr; xe::be thread_id; xe::be flags; } X_THREADNAME_INFO; static_assert_size(X_THREADNAME_INFO, 0x10); 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]); 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? } 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. // This is going to suck. xe::debugging::Break(); } DECLARE_XBOXKRNL_EXPORT2(RtlRaiseException, kDebug, kStub, kImportant); void KeBugCheckEx(dword_t code, dword_t param1, dword_t param2, dword_t param3, dword_t param4) { XELOGD("*** STOP: 0x%.8X (0x%.8X, 0x%.8X, 0x%.8X, 0x%.8X)", code, param1, param2, param3, param4); fflush(stdout); xe::debugging::Break(); assert_always(); } DECLARE_XBOXKRNL_EXPORT2(KeBugCheckEx, kDebug, kStub, kImportant); void KeBugCheck(dword_t code) { KeBugCheckEx(code, 0, 0, 0, 0); } DECLARE_XBOXKRNL_EXPORT2(KeBugCheck, kDebug, kImplemented, kImportant); void RegisterDebugExports(xe::cpu::ExportResolver* export_resolver, KernelState* kernel_state) {} } // namespace xboxkrnl } // namespace kernel } // namespace xe