mirror of
https://github.com/holub/mame
synced 2025-05-23 06:08:48 +03:00
On Windows, osd_break_into_debugger() will now dump a stack crawl
if there's no debugger attached. This means that asserts should have a full crawl now, for easier debugging.
This commit is contained in:
parent
8f8981db66
commit
3d1a55e19e
@ -123,6 +123,7 @@ public:
|
|||||||
FPTR sp() const { return m_stackframe.AddrStack.Offset; }
|
FPTR sp() const { return m_stackframe.AddrStack.Offset; }
|
||||||
FPTR frame() const { return m_stackframe.AddrFrame.Offset; }
|
FPTR frame() const { return m_stackframe.AddrFrame.Offset; }
|
||||||
|
|
||||||
|
bool reset();
|
||||||
void reset(CONTEXT &context, HANDLE thread);
|
void reset(CONTEXT &context, HANDLE thread);
|
||||||
bool unwind();
|
bool unwind();
|
||||||
|
|
||||||
@ -138,6 +139,7 @@ private:
|
|||||||
dynamic_bind<BOOL (WINAPI *)(HANDLE, LPCTSTR, BOOL)> m_sym_initialize;
|
dynamic_bind<BOOL (WINAPI *)(HANDLE, LPCTSTR, BOOL)> m_sym_initialize;
|
||||||
dynamic_bind<PVOID (WINAPI *)(HANDLE, DWORD64)> m_sym_function_table_access_64;
|
dynamic_bind<PVOID (WINAPI *)(HANDLE, DWORD64)> m_sym_function_table_access_64;
|
||||||
dynamic_bind<DWORD64 (WINAPI *)(HANDLE, DWORD64)> m_sym_get_module_base_64;
|
dynamic_bind<DWORD64 (WINAPI *)(HANDLE, DWORD64)> m_sym_get_module_base_64;
|
||||||
|
dynamic_bind<VOID (WINAPI *)(PCONTEXT)> m_rtl_capture_context;
|
||||||
|
|
||||||
static bool s_initialized;
|
static bool s_initialized;
|
||||||
};
|
};
|
||||||
@ -397,6 +399,10 @@ int main(int argc, char *argv[])
|
|||||||
pass_thru_filter = SetUnhandledExceptionFilter(exception_filter);
|
pass_thru_filter = SetUnhandledExceptionFilter(exception_filter);
|
||||||
SetErrorMode(SEM_FAILCRITICALERRORS | SEM_NOGPFAULTERRORBOX);
|
SetErrorMode(SEM_FAILCRITICALERRORS | SEM_NOGPFAULTERRORBOX);
|
||||||
|
|
||||||
|
// enable stack crawls for asserts
|
||||||
|
extern void (*s_debugger_stack_crawler)();
|
||||||
|
s_debugger_stack_crawler = winmain_dump_stack;
|
||||||
|
|
||||||
// if we're a GUI app, out errors to message boxes
|
// if we're a GUI app, out errors to message boxes
|
||||||
if (win_is_gui_application() || is_double_click_start(argc))
|
if (win_is_gui_application() || is_double_click_start(argc))
|
||||||
{
|
{
|
||||||
@ -582,6 +588,23 @@ static void osd_exit(running_machine &machine)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//============================================================
|
||||||
|
// winmain_dump_stack
|
||||||
|
//============================================================
|
||||||
|
|
||||||
|
void winmain_dump_stack()
|
||||||
|
{
|
||||||
|
// set up the stack walker
|
||||||
|
stack_walker walker;
|
||||||
|
if (!walker.reset())
|
||||||
|
return;
|
||||||
|
|
||||||
|
// walk the stack
|
||||||
|
while (walker.unwind())
|
||||||
|
fprintf(stderr, " %p: %p%s\n", (void *)walker.frame(), (void *)walker.ip(), (symbols == NULL) ? "" : symbols->symbol_for_address(walker.ip()));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
//============================================================
|
//============================================================
|
||||||
// check_for_double_click_start
|
// check_for_double_click_start
|
||||||
//============================================================
|
//============================================================
|
||||||
@ -755,14 +778,13 @@ static LONG WINAPI exception_filter(struct _EXCEPTION_POINTERS *info)
|
|||||||
|
|
||||||
// walk the stack
|
// walk the stack
|
||||||
while (walker.unwind())
|
while (walker.unwind())
|
||||||
fprintf(stderr, " %p: %p%s\n", (void *)walker.frame(), (void *)walker.ip(), symbols->symbol_for_address(walker.ip()));
|
fprintf(stderr, " %p: %p%s\n", (void *)walker.frame(), (void *)walker.ip(), (symbols == NULL) ? "" : symbols->symbol_for_address(walker.ip()));
|
||||||
|
|
||||||
// exit
|
// exit
|
||||||
return EXCEPTION_CONTINUE_SEARCH;
|
return EXCEPTION_CONTINUE_SEARCH;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
//**************************************************************************
|
//**************************************************************************
|
||||||
// STACK WALKER
|
// STACK WALKER
|
||||||
//**************************************************************************
|
//**************************************************************************
|
||||||
@ -778,7 +800,8 @@ stack_walker::stack_walker()
|
|||||||
m_stack_walk_64(TEXT("dbghelp.dll"), "StackWalk64"),
|
m_stack_walk_64(TEXT("dbghelp.dll"), "StackWalk64"),
|
||||||
m_sym_initialize(TEXT("dbghelp.dll"), "SymInitialize"),
|
m_sym_initialize(TEXT("dbghelp.dll"), "SymInitialize"),
|
||||||
m_sym_function_table_access_64(TEXT("dbghelp.dll"), "SymFunctionTableAccess64"),
|
m_sym_function_table_access_64(TEXT("dbghelp.dll"), "SymFunctionTableAccess64"),
|
||||||
m_sym_get_module_base_64(TEXT("dbghelp.dll"), "SymGetModuleBase64")
|
m_sym_get_module_base_64(TEXT("dbghelp.dll"), "SymGetModuleBase64"),
|
||||||
|
m_rtl_capture_context(TEXT("kernel32.dll"), "RtlCaptureContext")
|
||||||
{
|
{
|
||||||
// zap the structs
|
// zap the structs
|
||||||
memset(&m_stackframe, 0, sizeof(m_stackframe));
|
memset(&m_stackframe, 0, sizeof(m_stackframe));
|
||||||
@ -797,6 +820,34 @@ stack_walker::stack_walker()
|
|||||||
// reset - set up a new context
|
// reset - set up a new context
|
||||||
//-------------------------------------------------
|
//-------------------------------------------------
|
||||||
|
|
||||||
|
bool stack_walker::reset()
|
||||||
|
{
|
||||||
|
// set up the initial state
|
||||||
|
if (!m_rtl_capture_context)
|
||||||
|
return false;
|
||||||
|
(*m_rtl_capture_context)(&m_context);
|
||||||
|
m_thread = GetCurrentThread();
|
||||||
|
m_first = true;
|
||||||
|
|
||||||
|
// initialize the stackframe
|
||||||
|
memset(&m_stackframe, 0, sizeof(m_stackframe));
|
||||||
|
m_stackframe.AddrPC.Mode = AddrModeFlat;
|
||||||
|
m_stackframe.AddrFrame.Mode = AddrModeFlat;
|
||||||
|
m_stackframe.AddrStack.Mode = AddrModeFlat;
|
||||||
|
|
||||||
|
// pull architecture-specific fields from the context
|
||||||
|
#ifdef PTR64
|
||||||
|
m_stackframe.AddrPC.Offset = m_context.Rip;
|
||||||
|
m_stackframe.AddrFrame.Offset = m_context.Rsp;
|
||||||
|
m_stackframe.AddrStack.Offset = m_context.Rsp;
|
||||||
|
#else
|
||||||
|
m_stackframe.AddrPC.Offset = m_context.Eip;
|
||||||
|
m_stackframe.AddrFrame.Offset = m_context.Ebp;
|
||||||
|
m_stackframe.AddrStack.Offset = m_context.Esp;
|
||||||
|
#endif
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
void stack_walker::reset(CONTEXT &initial, HANDLE thread)
|
void stack_walker::reset(CONTEXT &initial, HANDLE thread)
|
||||||
{
|
{
|
||||||
// set up the initial state
|
// set up the initial state
|
||||||
|
@ -149,3 +149,4 @@ void CLIB_DECL mame_printf_verbose(const char *text, ...) ATTR_PRINTF(1,2);
|
|||||||
|
|
||||||
// use this to ping the watchdog
|
// use this to ping the watchdog
|
||||||
void winmain_watchdog_ping(void);
|
void winmain_watchdog_ping(void);
|
||||||
|
void winmain_dump_stack();
|
||||||
|
@ -50,6 +50,7 @@
|
|||||||
// MAMEOS headers
|
// MAMEOS headers
|
||||||
#include "winutf8.h"
|
#include "winutf8.h"
|
||||||
#include "strconv.h"
|
#include "strconv.h"
|
||||||
|
#include "strconv.h"
|
||||||
|
|
||||||
|
|
||||||
//============================================================
|
//============================================================
|
||||||
@ -67,6 +68,14 @@
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//============================================================
|
||||||
|
// GLOBAL VARIABLES
|
||||||
|
//============================================================
|
||||||
|
|
||||||
|
void (*s_debugger_stack_crawler)() = NULL;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
//============================================================
|
//============================================================
|
||||||
// osd_malloc
|
// osd_malloc
|
||||||
//============================================================
|
//============================================================
|
||||||
@ -167,4 +176,6 @@ void osd_break_into_debugger(const char *message)
|
|||||||
win_output_debug_string_utf8(message);
|
win_output_debug_string_utf8(message);
|
||||||
DebugBreak();
|
DebugBreak();
|
||||||
}
|
}
|
||||||
|
else if (s_debugger_stack_crawler != NULL)
|
||||||
|
(*s_debugger_stack_crawler)();
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user