Date: Sun, 24 May 1998 20:27:25 +0300 (IDT) From: Eli Zaretskii To: DJ Delorie cc: djgpp-workers AT delorie DOT com Subject: A better stack dump Message-ID: MIME-Version: 1.0 Content-Type: TEXT/PLAIN; charset=US-ASCII Precedence: bulk Here's a change that will make it possible to tell if the program bombed due to stack overflow (or other stack-related atrocities). The idea belongs to Charles Sandmann; the bugs are, as always, mine alone. *** src/libc/go32/dpmiexcp.c~2 Sat Mar 14 20:28:34 1998 --- src/libc/go32/dpmiexcp.c Sat May 23 17:27:06 1998 *************** *** 25,30 **** --- 25,32 ---- extern unsigned end __asm__ ("end"); static unsigned char old_video_mode = 3; static int cbrk_vect = 0x1b; /* May be 0x06 for PC98 */ + extern unsigned _stklen; + extern unsigned __djgpp_stack_limit; /* These are all defined in exceptn.S and only used here */ extern int __djgpp_exception_table; *************** extern int __djgpp_iret, __djgpp_i24; *** 35,40 **** --- 37,43 ---- extern void __djgpp_cbrk_hdlr(void); extern int __djgpp_hw_lock_start, __djgpp_hw_lock_end; extern __dpmi_paddr __djgpp_old_kbd; + extern unsigned djgpp_exception_stack __asm__("exception_stack"); static void itox(int v, int len) *************** show_call_frame(void) *** 95,106 **** { unsigned *vbp, *vbp_new, *tos; unsigned veip; ! int max=_farpeekb(_dos_ds, 0x484) + 1; ! if (max < 10 || max > 75) /* sanity check */ ! max = 10; /* 10 worked for v2.0 and v2.01 */ else ! max -= 14; /* 12 lines of preamble + 2 for symify */ tos = (unsigned *)__djgpp_selector_limit; vbp = (unsigned *)__djgpp_exception_state->__ebp; --- 98,117 ---- { unsigned *vbp, *vbp_new, *tos; unsigned veip; ! int max; ! if (isatty(STDERR_FILENO)) ! { ! max =_farpeekb(_dos_ds, 0x484) + 1; /* number of screen lines */ ! if (max < 10 || max > 75) /* sanity check */ ! max = 10; /* 10 worked for v2.0 and v2.01 */ ! else ! max -= 15; /* 13 lines of preamble + 2 for symify */ ! } else ! /* This could be MAX_INT. But the stack can be scrogged, so we ! limit by the maximum that the stack could hold (2 int's per frame). */ ! max = _stklen / (2*sizeof(unsigned)); tos = (unsigned *)__djgpp_selector_limit; vbp = (unsigned *)__djgpp_exception_state->__ebp; *************** do_faulting_finish_message(int fake_exce *** 173,178 **** --- 184,190 ---- { const char *en; unsigned long signum = __djgpp_exception_state->__signum; + unsigned excpt_stack_addr = (unsigned)&djgpp_exception_stack; int i; /* check video mode for original here and reset (not if PC98) */ *************** do_faulting_finish_message(int fake_exce *** 248,253 **** --- 260,269 ---- dump_selector("fs", __djgpp_exception_state->__fs); dump_selector("gs", __djgpp_exception_state->__gs); dump_selector("ss", __djgpp_exception_state->__ss); + err("App stack: ["); itox(__djgpp_stack_limit+_stklen, 8); + err(".."); itox(__djgpp_stack_limit, 8); + err("] Exceptn stack: ["); itox(excpt_stack_addr+8000, 8); + err(".."); itox(excpt_stack_addr, 8); err("]\r\n"); err("\r\n"); if (__djgpp_exception_state->__cs == _my_cs()) show_call_frame(); *************** signal(int sig, SignalHandler func) *** 273,278 **** --- 289,296 ---- } static const char signames[] = "ABRTFPE ILL SEGVTERMALRMHUP INT KILLPIPEQUITUSR1USR2NOFPTRAP"; + + void __djgpp_traceback_exit(int); void __djgpp_traceback_exit(int sig) { *** src/libc/go32/exceptn.S~0 Sun Dec 10 20:36:18 1995 --- src/libc/go32/exceptn.S Sat May 23 17:27:42 1998 *************** *** 24,30 **** /* Length 64 bytes plus non-used FPU */ .data .align 4 ! .lcomm exception_stack, 8000 .text .align 4 --- 24,30 ---- /* Length 64 bytes plus non-used FPU */ .data .align 4 ! .comm exception_stack, 8000 .text .align 4 *** src/docs/kb/wc202.~10 Sat May 23 17:34:56 1998 --- src/docs/kb/wc202.txi Sat May 23 17:53:10 1998 *************** *** 368,370 **** --- 368,388 ---- @code{errno} to be zero at the beginning of @code{main}, so it is now reset to zero before calling @code{main}. @vindex errno + + The stack dump printed when a program is aborted or crashes was + improved. First, it is no longer limited to 10 stack frames. When the + standard error stream is connected to the console, the maximum number of + frames is computed so that the stack dump will use all the available + screen area, without scrolling off the visible part. For example, at + 50-line display, you can have as much as 36 stack frames printed and + still see the registers and selectors dump, and the exception mnemonic + that preceed it. + + When stderr is not the console, the number of printed stack frames is + only limited by the stack size of the running program. + + In addition, the top and bottom of both the application code stack and + the locked stack used for processing exceptions, are printed. This + makes detection of stack overflows and other stack-related atrocities + much easier. + @cindex stack dump, when aborted or crashed