/** ****************************************************************************** * 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/objects/xthread.h" #include "xenia/kernel/util/shim_utils.h" #include "xenia/kernel/xboxkrnl_private.h" #include "xenia/xbox.h" namespace xe { namespace kernel { void DbgBreakPoint() { xe::debugging::Break(); } DECLARE_XBOXKRNL_EXPORT(DbgBreakPoint, ExportTag::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); // https://msdn.microsoft.com/en-us/library/windows/desktop/aa363082.aspx typedef struct { xe::be exception_code; xe::be exception_flags; xe::be exception_record; xe::be exception_address; xe::be number_parameters; xe::be exception_information[15]; } X_EXCEPTION_RECORD; static_assert_size(X_EXCEPTION_RECORD, 0x50); void AppendParam(StringBuffer* string_buffer, pointer_t record) { string_buffer->AppendFormat("%.8X(%.8X)", record.guest_address(), uint32_t(record->exception_code)); } void RtlRaiseException(pointer_t 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(&record->exception_information[0]); assert_true(thread_info->type == 0x1000); 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? return; } if (record->exception_code == 0xE06D7363) { // C++ exception. // http://blogs.msdn.com/b/oldnewthing/archive/2010/07/30/10044061.aspx xe::debugging::Break(); return; } // TODO(benvanik): unwinding. // This is going to suck. xe::debugging::Break(); } DECLARE_XBOXKRNL_EXPORT(RtlRaiseException, ExportTag::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_EXPORT(KeBugCheckEx, ExportTag::kImportant); void KeBugCheck(dword_t code) { KeBugCheckEx(code, 0, 0, 0, 0); } DECLARE_XBOXKRNL_EXPORT(KeBugCheck, ExportTag::kImportant); } // namespace kernel } // namespace xe void xe::kernel::xboxkrnl::RegisterDebugExports( xe::cpu::ExportResolver* export_resolver, KernelState* kernel_state) {}