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
>
>   


Reply via email to