diff options
author | Aaron Giles <aaron@aarongiles.com> | 2010-09-10 17:34:52 +0000 |
---|---|---|
committer | Aaron Giles <aaron@aarongiles.com> | 2010-09-10 17:34:52 +0000 |
commit | 3d1a55e19e71ba6dc117d6f4081f10e4c6b556b5 (patch) | |
tree | bd56ecc7046e5886c14caa41edc1b65cfbd3afe4 | |
parent | 8f8981db66ef18c674ee9a3f336b7f048a1dde9a (diff) |
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.
-rw-r--r-- | src/osd/windows/winmain.c | 61 | ||||
-rw-r--r-- | src/osd/windows/winmain.h | 1 | ||||
-rw-r--r-- | src/osd/windows/winmisc.c | 11 |
3 files changed, 68 insertions, 5 deletions
diff --git a/src/osd/windows/winmain.c b/src/osd/windows/winmain.c index f47c6ff2fed..2a8a606923e 100644 --- a/src/osd/windows/winmain.c +++ b/src/osd/windows/winmain.c @@ -118,11 +118,12 @@ class stack_walker { public: stack_walker(); - + FPTR ip() const { return m_stackframe.AddrPC.Offset; } FPTR sp() const { return m_stackframe.AddrStack.Offset; } FPTR frame() const { return m_stackframe.AddrFrame.Offset; } + bool reset(); void reset(CONTEXT &context, HANDLE thread); bool unwind(); @@ -138,6 +139,7 @@ private: dynamic_bind<BOOL (WINAPI *)(HANDLE, LPCTSTR, BOOL)> m_sym_initialize; 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<VOID (WINAPI *)(PCONTEXT)> m_rtl_capture_context; static bool s_initialized; }; @@ -392,11 +394,15 @@ int main(int argc, char *argv[]) // allocate symbols symbol_manager local_symbols(argv[0]); symbols = &local_symbols; - + // set up exception handling pass_thru_filter = SetUnhandledExceptionFilter(exception_filter); 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 (win_is_gui_application() || is_double_click_start(argc)) { @@ -583,6 +589,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 //============================================================ @@ -755,14 +778,13 @@ static LONG WINAPI exception_filter(struct _EXCEPTION_POINTERS *info) // walk the stack 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 return EXCEPTION_CONTINUE_SEARCH; } - //************************************************************************** // STACK WALKER //************************************************************************** @@ -778,7 +800,8 @@ stack_walker::stack_walker() m_stack_walk_64(TEXT("dbghelp.dll"), "StackWalk64"), m_sym_initialize(TEXT("dbghelp.dll"), "SymInitialize"), 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 memset(&m_stackframe, 0, sizeof(m_stackframe)); @@ -797,6 +820,34 @@ stack_walker::stack_walker() // 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) { // set up the initial state diff --git a/src/osd/windows/winmain.h b/src/osd/windows/winmain.h index 7bd962bc14e..2251d717ec1 100644 --- a/src/osd/windows/winmain.h +++ b/src/osd/windows/winmain.h @@ -149,3 +149,4 @@ void CLIB_DECL mame_printf_verbose(const char *text, ...) ATTR_PRINTF(1,2); // use this to ping the watchdog void winmain_watchdog_ping(void); +void winmain_dump_stack(); diff --git a/src/osd/windows/winmisc.c b/src/osd/windows/winmisc.c index 73f7a48bc5c..078f0b25835 100644 --- a/src/osd/windows/winmisc.c +++ b/src/osd/windows/winmisc.c @@ -50,6 +50,7 @@ // MAMEOS headers #include "winutf8.h" #include "strconv.h" +#include "strconv.h" //============================================================ @@ -68,6 +69,14 @@ //============================================================ +// GLOBAL VARIABLES +//============================================================ + +void (*s_debugger_stack_crawler)() = NULL; + + + +//============================================================ // osd_malloc //============================================================ @@ -167,4 +176,6 @@ void osd_break_into_debugger(const char *message) win_output_debug_string_utf8(message); DebugBreak(); } + else if (s_debugger_stack_crawler != NULL) + (*s_debugger_stack_crawler)(); } |