summaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
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
commit3d1a55e19e71ba6dc117d6f4081f10e4c6b556b5 (patch)
treebd56ecc7046e5886c14caa41edc1b65cfbd3afe4
parent8f8981db66ef18c674ee9a3f336b7f048a1dde9a (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.c61
-rw-r--r--src/osd/windows/winmain.h1
-rw-r--r--src/osd/windows/winmisc.c11
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)();
}