Hi Brian, Brian Xu - Sun Microsystems - Beijing China wrote: > Hi, > > I have a question: how the cmd '::findstack -v' in mdb works? > > Likewise in sparc, since at any time only the current register window > can be accessed, so if we want to backtrace the stack, we can only > access the fp(i6) and args(i0-i5) of the function's father, and how we > can access those of the grandfather, great grandfather, etc? > >
|SPARC uses register windows for most argument passing. Basically, if a function executes the "save" instruction at or near the beginning and the "restore" instruction at the end, there is a save area for registers on the stack. When a thread switch occurs, or a window spill trap occurs (a save executed, but no more windows), the register window(s) that need to be saved are placed in the save area on the stack. If a function does not use save/restore, arguments are in the output registers. There are six registers used for argument passing. If a function takes more than 6 arguments, the additional arguments are placed in the caller's frame at a fixed location from the top. The following shows an example. Note that for 64-bit SPARC, the stack pointer (%sp) and the frame pointer (%fp) are adjusted by 0x7ff (the ABI-Bias). The bias is there for two reasons. First, it allows trap handling code to quickly determine if it needs to save 32-bit or 64-bit values (with the bias, 64-bit stack pointer is always an odd number (lowest bit set)). Second, it allows more space to be accessed using "immediate" addressing (for example, "ld [%fp+offset], %l0"). "offset" is an immediate value and is a signed, 13-bit value. By using the abi-bias, the range of stack addresses that can be accessed with immediate addressing is increased. Let me know if you want more information on this. # *mdb -k* *::threadlist* *-v* /<-- stack backtrace for all kernel threads/ /< output truncated >/ ============== thread_id 30000aa5500 0x30000b2ced9: process args /usr/sbin/inetd -s /<-- inetd / 0x30000aa5610: lwp procp wchan 30000b4dba0 30000b2ca48 300007fe87a 0x30000aa5538: pc sp cv_wait_sig_swap+0x184 2a1003650a1 <-- stack pointer is odd (i.e., has ABI-bias)// cv_waituntil_sig+0x14(300007fe87a, 300007fe840, 0, 0, 3b, 20) poll+0x424(ffbff5f8, 30000998d08, 3000004ec48, ffffffffffffffff, 0, 188) syscall_trap32+0xa8(ffbff5f8, 31, ffffffffffffffff, 0, 1c, 40) /< output truncated >/ *2a1003650a1$c* /<-- 2a1003650a1 is sp of inetd/ cv_waituntil_sig+0x14(300007fe87a, 300007fe840, 0, 0, 3b, 20) poll+0x424(ffbff5f8, 30000998d08, 3000004ec48, ffffffffffffffff, 0, 188) syscall_trap32+0xa8(ffbff5f8, 31, ffffffffffffffff, 0, 1c, 40) *2a1003650a1$C* /<-- upper-case $C gives frame pointer at each frame/ 000002a100365151 cv_waituntil_sig+0x14(300007fe87a, 300007fe840, 0, 0, 3b, 20) 000002a100365211 poll+0x424(ffbff5f8, 30000998d08, 3000004ec48, ffffffffffffffff , 0, 188) 000002a1003652f1 syscall_trap32+0xa8(ffbff5f8, 31, ffffffffffffffff, 0, 1c, 40) *30000aa5500::print kthread_t t_pcb* /<-- get the pc and sp from the thread of inetd/ { t_pcb.val = [ 0x107bd1c, 0x2a1003650a1 ] } *107bd1c/ai* /<-- same pc as threadlist shows/ cv_wait_sig_swap+0x184: cv_wait_sig_swap+0x184: call -0x3aeb4 | The following shows the register save areas for each stack frame for |inetd|. | *2a1003650a1+7ff,10/K* /<-- must add V9 bias, display 16 64-bit hex values/ 0x2a1003658a0: 30000b4dba0 30000b2ca48 0 300007fe87a /<-- %l0-%l3/ 938 0 30000aa5500 fffd /<-- %l4-%l7/ 0 300007fe840 20 3000004edce /<-- %i0-%i3/ 2a100365a00 0 2a100365151 107c14c /<-- %i4-%i7/ *107c14c/ai* /<-- %i7 is saved program counter/ cv_waituntil_sig+0x14: cv_waituntil_sig+0x14: call -0x5b4 *2a100365151+7ff,10/K* /<-- %i6 is saved frame pointer, use to get previous frame/ 0x2a100365950: 0 3000004ec48 3b 0 30000c05798 30 300007fe840 30000bbb600 300007fe87a 300007fe840 0 0 3b 20 2a100365211 10bb378 *10bb378/ai* /<-- and repeat.../ poll+0x424: poll+0x424: call -0x3f240 *2a100365211+7ff,10/K* 0x2a100365a10: 30000998d48 300007fe840 0 31 30000998d58 0 0 0 ffbff5f8 30000998d08 3000004ec48 ffffffffffffffff 0 188 2a1003652f1 10343fc *10343fc/ai* /<-- and again.../ syscall_trap32+0xa8: syscall_trap32+0xa8: jmpl %g3, %o7 *2a1003652f1+7ff,10/K* 0x2a100365af0: 1007254 2a100365ba0 30000b4dba0 1034354 1448000 0 30000aa5500 2a100365ba0 ffbff5f8 31 ffffffffffffffff 0 1c 40 ffbff598 ff14d474 *ff14d474/ai* /<-- and again, but here kernel is returning to user address/ 0xff14d474: mdb: failed to read instruction at ff14d474: no mapping for address 0xff14d474: In the above output, each frame's window save area is displayed. Hope this helps. For 32-bit programs, the technique is the same, only you don't add 7ff, since the ABI-bias is not used. Basically, ::findstack does the same walk that I am doing by hand in the above output. max | > Thanks, > Brian > > _______________________________________________ > mdb-discuss mailing list > mdb-discuss at opensolaris.org > >