Tidyed up stack backtrace code a bit, and added a simple special
case for backtracing from a null EIP.

diff --git a/debugger/stack.c b/debugger/stack.c
index 8e4c99f..1eb45ac 100644
--- a/debugger/stack.c
+++ b/debugger/stack.c
@@ -79,7 +79,7 @@
 }
 
 #ifdef __i386__
-static void DEBUG_ForceFrame(DBG_ADDR *stack, DBG_ADDR *code, int frameno, int bits, int noisy)
+static void DEBUG_ForceFrame(DBG_ADDR *stack, DBG_ADDR *code, int frameno, int bits, int noisy, const char *caveat)
 {
     int theframe = nframe++;
     frames = (struct bt_info *)DBG_realloc(frames,
@@ -99,16 +99,16 @@
     frames[theframe].ss = stack->seg;
     frames[theframe].ebp = stack->off;
     if (noisy) {
-      DEBUG_Printf( DBG_CHN_MESG, (bits == 16) ? " (bp=%04lx)\n" : " (ebp=%08lx)\n", stack->off );
+      DEBUG_Printf( DBG_CHN_MESG, (bits == 16) ? " (bp=%04lx%s)\n" : " (ebp=%08lx%s)\n", stack->off, caveat?caveat:"" );
     }
 }
 
 static BOOL DEBUG_Frame16(DBG_ADDR *addr, unsigned int *cs, int frameno, int noisy)
 {
-    unsigned int	ss = addr->seg, possible_cs = 0;
+    unsigned int	possible_cs = 0;
     FRAME16 		frame;
-    int 		theframe = nframe;
     void*		p = (void*)DEBUG_ToLinear(addr);
+    DBG_ADDR		code;
     
     if (!p) return FALSE;
     
@@ -117,12 +117,7 @@
 	return FALSE;
     }
     if (!frame.bp) return FALSE;
-    nframe++;
-    frames = (struct bt_info *)DBG_realloc(frames,
-					   nframe*sizeof(struct bt_info));
-    if (noisy)
-        DEBUG_Printf(DBG_CHN_MESG,"%s%d ", (theframe == curr_frame ? "=>" : "  "),
-		     frameno);
+
     if (frame.bp & 1) *cs = frame.cs;
     else {
         /* not explicitly marked as far call,
@@ -138,33 +133,19 @@
 	    }
 	}
     }
-    frames[theframe].cs = addr->seg = *cs;
-    frames[theframe].eip = addr->off = frame.ip;
-    if (noisy)
-        frames[theframe].frame = DEBUG_PrintAddressAndArgs( addr, 16, 
-							    frame.bp, TRUE );
-    else
-        DEBUG_FindNearestSymbol( addr, TRUE, 
-				 &frames[theframe].frame.sym, frame.bp, 
-				 &frames[theframe].frame.list);
-    frames[theframe].ss = addr->seg = ss;
-    frames[theframe].ebp = addr->off = frame.bp & ~1;
-    if (noisy) {
-        DEBUG_Printf( DBG_CHN_MESG, " (bp=%04lx", addr->off );
-        if (possible_cs) {
-	    DEBUG_Printf( DBG_CHN_MESG, ", far call assumed" );
-	}
-	DEBUG_Printf( DBG_CHN_MESG, ")\n" );
-    }
+    code.seg = *cs;
+    code.off = frame.ip;
+    addr->off = frame.bp & ~1;
+    DEBUG_ForceFrame(addr, &code, frameno, 16, noisy, possible_cs ? ", far call assumed" : NULL );
     return TRUE;
 }
 
 static BOOL DEBUG_Frame32(DBG_ADDR *addr, unsigned int *cs, int frameno, int noisy)
 {
-    unsigned int 	ss = addr->seg;
     FRAME32 		frame;
-    int 		theframe = nframe;
     void*		p = (void*)DEBUG_ToLinear(addr);
+    DBG_ADDR		code;
+    DWORD		old_bp = addr->off;
     
     if (!p) return FALSE;
     
@@ -173,27 +154,12 @@
        return FALSE;
     }
     if (!frame.ip) return FALSE;
-    
-    nframe++;
-    frames = (struct bt_info *)DBG_realloc(frames,
-					   nframe*sizeof(struct bt_info));
-    if (noisy)
-       DEBUG_Printf(DBG_CHN_MESG,"%s%d ", (theframe == curr_frame ? "=>" : "  "),
-		    frameno);
-    frames[theframe].cs = addr->seg = *cs;
-    frames[theframe].eip = addr->off = frame.ip;
-    if (noisy)
-        frames[theframe].frame = DEBUG_PrintAddressAndArgs( addr, 32, 
-							    frame.bp, TRUE );
-    else
-        DEBUG_FindNearestSymbol( addr, TRUE, 
-				 &frames[theframe].frame.sym, frame.bp, 
-				 &frames[theframe].frame.list);
-    if (noisy) DEBUG_Printf( DBG_CHN_MESG, " (ebp=%08lx)\n", frame.bp );
-    frames[theframe].ss = addr->seg = ss;
-    frames[theframe].ebp = frame.bp;
-    if (addr->off == frame.bp) return FALSE;
+
+    code.seg = *cs;
+    code.off = frame.ip;
     addr->off = frame.bp;
+    DEBUG_ForceFrame(addr, &code, frameno, 32, noisy, NULL);
+    if (addr->off == old_bp) return FALSE;
     return TRUE;
 }
 #endif
@@ -218,11 +184,10 @@
 
     if (noisy) DEBUG_Printf( DBG_CHN_MESG, "Backtrace:\n" );
 
-    nframe = 1;
+    nframe = 0;
     if (frames) DBG_free( frames );
-    frames = (struct bt_info *) DBG_alloc( sizeof(struct bt_info) );
-    if (noisy)
-        DEBUG_Printf(DBG_CHN_MESG,"%s%d ",(curr_frame == 0 ? "=>" : "  "), frameno);
+    /* frames = (struct bt_info *) DBG_alloc( sizeof(struct bt_info) ); */
+    frames = NULL;
 
     if (DEBUG_IsSelectorSystem(ss)) ss = 0;
     if (DEBUG_IsSelectorSystem(cs)) cs = 0;
@@ -231,29 +196,29 @@
     switch (DEBUG_GetSelectorType(ss))
     {
     case 32:
-        frames[0].cs = addr.seg = cs;
-        frames[0].eip = addr.off = DEBUG_context.Eip;
-        if (noisy)
-            frames[0].frame = DEBUG_PrintAddress( &addr, 32, TRUE );
-        else
-	    DEBUG_FindNearestSymbol( &addr, TRUE, &frames[0].frame.sym, 0, 
-				     &frames[0].frame.list);
-        frames[0].ss = addr.seg = ss;
-	frames[0].ebp = addr.off = DEBUG_context.Ebp;
-        if (noisy) DEBUG_Printf( DBG_CHN_MESG, " (ebp=%08x)\n", frames[0].ebp );
+        code.seg = cs;
+        code.off = DEBUG_context.Eip;
+        addr.seg = ss;
+	addr.off = DEBUG_context.Ebp;
+        DEBUG_ForceFrame( &addr, &code, frameno, 32, noisy, NULL );
+        if (!(code.seg || code.off)) {
+            /* trying to execute a null pointer... yuck...
+             * if it was a call to null, the return EIP should be
+             * available at SS:ESP, so let's try to retrieve it */
+            tmp.seg = ss;
+            tmp.off = DEBUG_context.Esp;
+            if (DEBUG_READ_MEM(DEBUG_ToLinear(&tmp), &code.off, sizeof(code.off))) {
+                DEBUG_ForceFrame( &addr, &code, ++frameno, 32, noisy, ", null call assumed" );
+            }
+        }
         is16 = FALSE;
 	break;
     case 16:
-        frames[0].cs = addr.seg = cs;
-        frames[0].eip = addr.off = LOWORD(DEBUG_context.Eip);
-        if (noisy)
-	    frames[0].frame = DEBUG_PrintAddress( &addr, 16, TRUE );
-        else
-	    DEBUG_FindNearestSymbol( &addr, TRUE, &frames[0].frame.sym, 0, 
-				     &frames[0].frame.list);
-        frames[0].ss = addr.seg = ss;
-	frames[0].ebp = addr.off = LOWORD(DEBUG_context.Ebp);
-        if (noisy) DEBUG_Printf( DBG_CHN_MESG, " (bp=%04x)\n", frames[0].ebp );
+        code.seg = cs;
+        code.off = LOWORD(DEBUG_context.Eip);
+        addr.seg = ss;
+	addr.off = LOWORD(DEBUG_context.Ebp);
+        DEBUG_ForceFrame( &addr, &code, frameno, 16, noisy, NULL );
         is16 = TRUE;
 	break;
     default:
@@ -317,7 +282,7 @@
 	       cs = 0;
 	       addr.seg = 0;
 	       addr.off = frame32.ebp;
-	       DEBUG_ForceFrame( &addr, &code, ++frameno, 32, noisy );
+	       DEBUG_ForceFrame( &addr, &code, ++frameno, 32, noisy, NULL );
 	       
 	       next_switch = cur_switch;
 	       tmp.seg = SELECTOROF(next_switch);
@@ -351,7 +316,7 @@
 	      cs = frame16.cs;
 	      addr.seg = SELECTOROF(next_switch);
 	      addr.off = frame16.bp;
-	      DEBUG_ForceFrame( &addr, &code, ++frameno, 16, noisy );
+	      DEBUG_ForceFrame( &addr, &code, ++frameno, 16, noisy, NULL );
 	      
 	      next_switch = cur_switch;
 	      if (!DEBUG_READ_MEM((void*)next_switch, &frame32, sizeof(STACK32FRAME))) {