diff --git a/debugger/dbg.y b/debugger/dbg.y
index 9cd6849259fdeada6919f2ec7da76939a61c0d1f..2c18c2bf31eea5c8d657058f7243f3720062935e 100644
--- a/debugger/dbg.y
+++ b/debugger/dbg.y
@@ -52,7 +52,7 @@ int yyerror(char *);
 
 %token tCONT tPASS tSTEP tLIST tNEXT tQUIT tHELP tBACKTRACE tINFO tWALK tUP tDOWN
 %token tENABLE tDISABLE tBREAK tWATCH tDELETE tSET tMODE tPRINT tEXAM tABORT tVM86
-%token tCLASS tMAPS tMODULE tSTACK tSEGMENTS tREGS tWND tQUEUE tLOCAL
+%token tCLASS tMAPS tMODULE tSTACK tSEGMENTS tREGS tWND tQUEUE tLOCAL tEXCEPTION
 %token tPROCESS tTHREAD tMODREF tEOL tEOF
 %token tFRAME tSHARE tCOND tDISPLAY tUNDISPLAY tDISASSEMBLE
 %token tSTEPI tNEXTI tFINISH tSHOW tDIR tWHATIS tSOURCE
@@ -248,6 +248,8 @@ walk_command:
     | tWALK tWND tNUM tEOL      { DEBUG_WalkWindows( (HWND)$3, 0 ); }
     | tWALK tPROCESS tEOL       { DEBUG_WalkProcess(); }
     | tWALK tTHREAD tEOL        { DEBUG_WalkThreads(); }
+    | tWALK tEXCEPTION tEOL           { DEBUG_WalkExceptions(DEBUG_CurrTid); }
+    | tWALK tEXCEPTION tNUM tEOL      { DEBUG_WalkExceptions($3); }
     | tWALK tMODREF expr_value tEOL   { DEBUG_WalkModref( $3 ); DEBUG_FreeExprMem(); }
     ;
 
diff --git a/debugger/debug.l b/debugger/debug.l
index c3e09cf6aa6a760fd899d79c6a66b8ff4f626932..e8b3212b63e3cbd1efd1fc4f4639c06f723a22c1 100644
--- a/debugger/debug.l
+++ b/debugger/debug.l
@@ -148,6 +148,7 @@ STRING     \"[^\n"]+\"
 <INFO_CMD,WALK_CMD>process|proces|proce|proc   		{ return tPROCESS; }
 <INFO_CMD,WALK_CMD>threads|thread|threa|thre|thr|th { return tTHREAD; }
 <INFO_CMD,WALK_CMD>modref|modre|modr	{ return tMODREF; }
+<WALK_CMD>exception|except|exc|ex	{ return tEXCEPTION; }
 <INFO_CMD>registers|regs|reg|re		{ return tREGS; }
 <INFO_CMD>segments|segment|segm|seg|se	{ return tSEGMENTS; }
 <INFO_CMD>stack|stac|sta|st     	{ return tSTACK; }
diff --git a/debugger/debugger.h b/debugger/debugger.h
index 31da4a8a4e7fdcdf844ffda9ff5a38c4a58978a9..5dc26599fc1d2f10e9667d0cd82a6455ac2d449c 100644
--- a/debugger/debugger.h
+++ b/debugger/debugger.h
@@ -405,6 +405,7 @@ extern void DEBUG_DumpModule(DWORD mod);
 extern void DEBUG_WalkModules(void);
 extern void DEBUG_WalkProcess(void);
 extern void DEBUG_WalkThreads(void);
+extern void DEBUG_WalkExceptions(DWORD tid);
 extern void DEBUG_DumpQueue(DWORD q);
 extern void DEBUG_WalkQueues(void);
 extern void DEBUG_InfoSegments(DWORD s, int v);
diff --git a/debugger/info.c b/debugger/info.c
index 7a450ad92d1fbad108913a4c5e873b8c5db8e737..29b3c16da9b7cd2da5e959f51896273c8ecb376e 100644
--- a/debugger/info.c
+++ b/debugger/info.c
@@ -543,6 +543,59 @@ void DEBUG_WalkModref(DWORD p)
    DEBUG_Printf(DBG_CHN_MESG, "No longer walking module references list\n");
 }
 
+/***********************************************************************
+ *           DEBUG_WalkExceptions
+ *
+ * Walk the exception frames of a given thread.
+ */
+void DEBUG_WalkExceptions(DWORD tid)
+{
+    DBG_THREAD * thread;
+    void *next_frame;
+
+    DEBUG_Printf( DBG_CHN_MESG, "Exception frames:\n" );
+
+    if (tid == DEBUG_CurrTid) thread = DEBUG_CurrThread;
+    else
+    {
+         thread = DEBUG_GetThread(DEBUG_CurrProcess, tid);
+
+         if (!thread)
+         {
+              DEBUG_Printf( DBG_CHN_MESG, "Unknown thread id (0x%08lx) in current process\n", tid);
+              return;
+         }
+         if (SuspendThread( thread->handle ) == -1)
+         {
+              DEBUG_Printf( DBG_CHN_MESG, "Can't suspend thread id (0x%08lx)\n", tid);
+              return;
+         }
+    }
+
+    if (!DEBUG_READ_MEM(thread->teb, &next_frame, sizeof(next_frame)))
+    {
+        DEBUG_Printf( DBG_CHN_MESG, "Can't read TEB:except_frame\n");
+        return;
+    }
+
+    while (next_frame != (void *)-1)
+    {
+        EXCEPTION_FRAME frame;
+
+        DEBUG_Printf( DBG_CHN_MESG, "%p: ", next_frame );
+        if (!DEBUG_READ_MEM(next_frame, &frame, sizeof(frame)))
+        {
+            DEBUG_Printf( DBG_CHN_MESG, "Invalid frame address\n" );
+            break;
+        }
+        DEBUG_Printf( DBG_CHN_MESG, "prev=%p handler=%p\n", frame.Prev, frame.Handler );
+        next_frame = frame.Prev;
+    }
+
+    if (tid != DEBUG_CurrTid) ResumeThread( thread->handle );
+}
+
+
 void DEBUG_InfoSegments(DWORD start, int length)
 {
     char 	flags[3];