From: idr AT cs DOT pdx DOT edu (Ian D Romanick) Message-Id: <199609051735.KAA21363@sirius.cs.pdx.edu> Subject: Re: Stack Trace To: mikeday AT melbpc DOT org DOT au (Michael Day) Date: Thu, 5 Sep 1996 10:35:20 -0700 (PDT) Cc: djgpp AT delorie DOT com In-Reply-To: from "Michael Day" at Sep 5, 96 12:32:22 pm MIME-Version: 1.0 Content-Type: text/plain; charset=US-ASCII Content-Transfer-Encoding: 7bit > When a djgpp program crashes, it prints a nice stack trace which is very handy > for debugging. Is there anyway to generate this without actually crashing, ie: > if you want to find out how a particular procedure got called then insert a > line that generates the stacktrace? Or is this a CWSDPMI thing? /* Name : stak_dmp.c * * Notes: This file contains some simple routines that I use to help * debug programs. I use the IsPointerValid() function a lot * in assert() statements, and I modified my assert() macro to * call stack_trace(), then call exit(), rather than call abort(). */ #include /*****************************************************************************/ /* Name : IsFarPointerValid() * * Notes: This function is used to determin, in advance, if accessing the * specified pointer and selector will cause a GP fault. * * This code was taken from an older (1993ish) issue of * _PC_Techniques_. I only typed it in and GCCized it. */ int IsFarPointerValid( void * ptr, unsigned short selector ) { int retVal; asm( "xor %%eax,%%eax\n" /* assume failure */ "lar %%edx,%%ebx\n" /* validate the specified selctor */ "jnz fbail\n" "lsl %%edx,%%ebx\n" /* get the selector segment limit.. */ "jnz fbail\n" /* ..or an error if the selector.. */ /* ..can't be read. */ "cmp %%ecx,%%ebx\n" /* make sure the offset is less.. */ "jbe fbail\n" /* ..than the limit */ "verw %%edx\n" /* make sure the selector is.. */ "jnz fbail\n" /* ..writable (i.e., data) */ "inc %%eax\n" /* ptr must be valid to get here. */ "fbail:\n" /* bail out point for failure. */ : "=eax" (retVal) : "edx" (selector), "ecx" (ptr) : "ebx" ); return( retVal ); } /*****************************************************************************/ /* Name : IsPointerValid() * * Notes: This function works exactly like IsFarPointerValid(), except that * it uses the current %ds as the selector. */ int IsPointerValid( void * ptr ) { int retVal; asm( "xor %%edx,%%edx\n\t" "mov %%ds,%%dx\n\t" "xor %%eax,%%eax\n\t" /* assume failure */ "lar %%edx,%%ebx\n\t" /* validate the specified selctor */ "jnz bail\n\t" "lsl %%edx,%%ebx\n\t" /* get the selector segment limit.. */ "jnz bail\n\t" /* ..or an error if the selector.. */ /* ..can't be read. */ "cmp %%ecx,%%ebx\n\t" /* make sure the offset is less.. */ "jbe bail\n\t" /* ..than the limit */ "verw %%edx\n\t" /* make sure the selector is.. */ "jnz bail\n\t" /* ..writable (i.e., data) */ "inc %%eax\n\t" /* ptr must be valid to get here. */ "bail:\n" /* bail out point for failure. */ : "=eax" (retVal) : "ecx" (ptr) : "ebx" ); return( retVal ); } /*****************************************************************************/ /* Name : GetSS() * * Notes: Returns the current stack segment selector. * */ __inline__ short GetSS( void ) { short ss; asm( "movw %%ss,%w0\n" : "=r" (ss) ); return( ss ); } /*****************************************************************************/ /* Name : stack_trace() * * Notes: This code is used to print a symify compatible stack trace. It * is based on some code posted to the DJGPP mailing list sometime * ago. Search the archive at http://www.delorie.com/djgpp if you * really want to see the original. My major addition is the calls * to IsFarPointerValid(). I did this to prevent a crash in programs * compiled with GCC's -fomit-frame-pointer option. */ void stack_trace( FILE * file ) { long * bp; if ( file == NULL ) { file = stderr; } /* Get the frame pointer for this subroutine. */ bp = (long *) & bp + 1; /* Loop until we run out of frame pointers. */ while( bp[0] != NULL ) { if ( ! IsFarPointerValid( bp, GetSS() ) || ! IsFarPointerValid( bp + 1, GetSS() ) ) { break; } /* Print the return address for the current frame. */ fprintf( file, " 0x%08lx\n", bp[1] ); /* Follow the link to the next frame. */ bp = (long *) bp[0]; } } -- "Harshaw conceded that man, a social animal, could not avoid government, any more than an individual could escape bondage to his bowels." -- Stranger In A Strange Land See my bowels at http://www.cs.pdx.edu/~idr