peters@ti-csl.UUCP (04/07/87)
I am trying to construct a stack backtrace routine to run on a 68010 system we are building (Internal use only. This is not a product announcement.). I'm after the sort of thing that adb will give you when you use the $c command. Unfortunately, all of our Unix source is for the Vax, so I can't just lift the algorithm from adb. At any given point in time, the frame pointer (in our case, A6) is pointing at the previous value of A6, conveniently stored on the stack. Continuing to unwind the stack, you find the return address of the jsr, right next to where A6 is pointing now . Then the fun begins. Next in line is the top of the previous routine's stack. The bottom of the frame can be determined from the place A6 is pointing right now. Great, we've got the top of the stack and the bottom of the frame for the previous routine. Next you need to find the bottom of the stack (or the top of the frame) so you can distinguish the stack (parameters to the next routine) from the local variables (the frame of this routine). Easier said than done--at least I haven't figured out how to do it yet. I just keep bumping into this glob that's part frame and part stack (and I don't know how much of each). If anyone out there would care to enlighten me on this subject, I would be in your debt (figuratively speaking, of course).
peters@ti-csl.UUCP (04/07/87)
Almost forgot the signature..... -- Patrick Peters UUCP: ut-sally!im4u!ti-csl!tifsie!pat Texas Instruments sun!texsun!ti-csl!tifsie!pat PO Box 655012 M/S 3635 uiucdcs!convex!smu!tifsie!pat Dallas, TX 75265 Voice: (214)995-2786
terryl@tekcrl.UUCP (04/07/87)
In article <18534@ti-csl.CSNET> peters@ti-csl.CSNET (Pat Peters) writes: > >I am trying to construct a stack backtrace routine to run on a 68010 >system we are building (Internal use only. This is not a product >announcement.). I'm after the sort of thing that adb will give >you when you use the $c command. Unfortunately, all of our Unix >source is for the Vax, so I can't just lift the algorithm from adb. > > ....Delete many lines about A6, etc..... > Well, unfortunately, you don't say what system, or more importantly, what compiler you are using. I'll describe things the way the MIT C compiler works for a 68k machine: As you commented, A6 always points to the TOP of the stack frame (where TOP is defined as a HIGHER address than the BOTTOM of the stack frame, where stack frames grow DOWNWARDS) of the current procedure. At the TOP of the stack frame (i.e. what A6 points to) is the previous value of A6 (i.e. the TOP of the previous stack frame of the procedure that called the current procedure). Above the TOP of the stack frame is the return address of the procdeure that called the current procedure; above this is the arguments to the current procedure, and above that are the local variables and temporaries of the previous proce- dure. Believing that a picture is worth more than a thousand words, here is a graphical representation: +-------------------------------+ (Higher addresses) | Top of previous stack frame | | Local variables, temporaries | | and saved registers of pre- | | vious stack frame. | | Arguments to next frame. | | Return address to return to | | after next procedure is | | finished. | |-------------------------------| | Previous value of A6 (i.e. the| | address of the top of the pre-| | vious stack frame). | | Local variables, etc. | (Lower addresses) +-------------------------------+ So now what you need to do a complete C stack trace back is: The current value of A6 (so you can find the current value of the TOP of the current stack frame), and the Program Counter (so you can tell what procedure you are in). Everything else can be found from the above description. A6 points to the TOP of the previous stack frame; at A6+4 is the return address, so now you can find what procedure called this procedure. Keep following this chain until you find the end of the stack frames (unfortunately, this is not compiler specific but system specific. For our 68k systems, in the C runtime startup, we put a zero value into A6, so when we have a zero value for the TOP of the previous stack frame, we know we are done). Well, what about arguments to routines, you ask??? Well, again, this is compiler specific. There is no way to explicitly know how many arguments are passed to a routine, unlike the VAX where the calling convention says you have to specify it. Luckily, some compilers help us out on this respect. Speci- fically, the MIT C compiler always returns to an add-type instruction to pop off the arguments, so if you look up the instruction to return to, you can find out how many bytes were passed as arguments. Even luckier, the MIT C compiler also pushes ALL non-floating point and structure arguments as a four- byte quantity; it pushes floating point arguments as doubles, and structures as-is. So without more knowledge about what kind of arguments were pushed, you can only make a guess, usually that all arguments are simple four-byte non-floating point, non-structure type arguments. Also note that arguments to routines are actually part of the calling routine's stack frame, and are not part of the called routine's stack frame. Hope this helps soemwhat. Terry Laskodi of Tektronix
peters@ti-csl.UUCP (04/08/87)
in article <755@killer.UUCP>, jfh@killer.UUCP (John Haugh) says: > > In article <18534@ti-csl.CSNET>, peters@ti-csl.CSNET (Pat Peters) writes: >> >> I am trying to construct a stack backtrace routine to run on a 68010 >> system we are building.... > > The stack on a M68000 looks something like this: > > SP + a bunch: <ARG N> > . > . > <ARG 0> > <RETURN ADDRESS> > FP: <SAVED FRAME POINTER> ..... > Take that return address and find the instruction after the > jsr instruction. (Easy - it is at the return address.) Decode this > instruction to figure out how many arguments there were. Nice thought (in fact one I already had) but, 1. Inconvenient because the compiler will use several (I believe at least three different) ways of unwinding the stack. They are documented, however. 2. I've seen the compiler decide to unwind the stack at some time other than on return (the instruction at the return address may not be the one that restores the stack pointer). In case you're wondering, we use Green Hills C. The optimizer does some wonderful (but strange) things to the code. There is an option that will force generation of stack frames (put in specifically to facilitate back tracing the stack), but I don't see anywhere in the manual where they promise that the instruction pointed to by the return address is the one (of three types) that will restore the stack pointer. -- Patrick Peters UUCP: ut-sally!im4u!ti-csl!tifsie!pat Texas Instruments sun!texsun!ti-csl!tifsie!pat PO Box 655012 M/S 3635 uiucdcs!convex!smu!tifsie!pat Dallas, TX 75265 Voice: (214)995-2786
kent@rose4.Rosemount.COM (Kent Schnaith) (04/09/87)
Use the return address and look at the instruction, it should be addl #N,a7 or something. Its pretty easy to decode the instruction since only a few combinations may be used. N is the size of the paramters passed. Assuming your compiler works like ours of course.