Section 14.3. Switching MDB to Debug a Specific Process


14.3. Switching MDB to Debug a Specific Process

An mdb command, <proc address>::context, switches a context to a specified user process.

> ffffffff866f1878::context debugger context set to proc ffffffff866f1878 


After the context is switched, several mdb commands return process information rather than kernel information. For example:

> ::nm Value              Size               Type  Bind  Other Shndx    Name 0x0000000000000000|0x0000000000000000|NOTY |LOCL |0x0  |UNDEF   | 0x0000000008056c29|0x0000000000000076|FUNC |GLOB |0x0  |10      |gethost_revalidate 0x0000000008056ad2|0x0000000000000024|FUNC |GLOB |0x0  |10      |getgr_uid_reaper 0x000000000805be5f|0x0000000000000000|OBJT |GLOB |0x0  |14      |_etext 0x0000000008052778|0x0000000000000000|FUNC |GLOB |0x0  |UNDEF   |strncpy 0x0000000008052788|0x0000000000000000|FUNC |GLOB |0x0  |UNDEF   |_uncached_getgrnam_r 0x000000000805b364|0x000000000000001b|FUNC |GLOB |0x0  |12      |_fini 0x0000000008058f54|0x0000000000000480|FUNC |GLOB |0x0  |10      |nscd_parse 0x0000000008052508|0x0000000000000000|FUNC |GLOB |0x0  |UNDEF   |pause 0x00000000080554e0|0x0000000000000076|FUNC |GLOB |0x0  |10      |getpw_revalidate ... > ::mappings             BASE            LIMIT             SIZE NAME          8046000          8048000             2000 [ anon ]          8050000          805c000             c000 /usr/sbin/nscd          806c000          806e000             2000 /usr/sbin/nscd          806e000          80f0000            82000 [ anon ]         fd650000         fd655000             5000 /lib/nss_files.so.1         fd665000         fd666000             1000 /lib/nss_files.so.1         fd680000         fd690000            10000 [ anon ]         fd6a0000         fd79e000            fe000 [ anon ]         fd7a0000         fd89e000            fe000 [ anon ] ... 


14.3.1. Constructing the Process Stack

Unlike examining the kernel, where we would ordinarily use the stack-related mdb commands like ::stack or ::findstack, we need to use stack pointers to traverse a process stack. In this case, nscd is an x86 32-bit application. So a "stack pointer + 0x38" and a "stack pointer + 0x3c" shows the stack pointer and the program counter of the previous frame.

/*  * In the Intel world, a stack frame looks like this:  *  * %fp0->|                               |  *       |-------------------------------|  *       |  Args to next subroutine      |  *       |-------------------------------|-\  * %sp0->|  One-word struct-ret address  | |  *       |-------------------------------|  > minimum stack frame  * %fp1->|  Previous frame pointer (%fp0)| |  *       |-------------------------------|-/  *       |  Local variables              |  * %sp1->|-------------------------------|  *  * For amd64, the minimum stack frame is 16 bytes and the frame pointer must  * be 16-byte aligned.  */ struct frame {         greg_t  fr_savfp;               /* saved frame pointer */         greg_t  fr_savpc;               /* saved program counter */ }; #ifdef _SYSCALL32 /*  * Kernel's view of a 32-bit stack frame.  */ struct frame32 {         greg32_t fr_savfp;              /* saved frame pointer */         greg32_t fr_savpc;              /* saved program counter */ };                                                                         See sys/stack.h 


Each individual stack frame is defined as follows:

/*  * In the x86 world, a stack frame looks like this:  *  *              |---------------------------|  * 4n+8(%ebp) ->| argument word n           |  *              | ...                       |    (Previous frame)  *    8(%ebp) ->| argument word 0           |  *              |---------------------------|--------------------  *    4(%ebp) ->| return address            |  *              |---------------------------|  *    0(%ebp) ->| previous %ebp (optional)  |  *              |---------------------------|  *   -4(%ebp) ->| unspecified               |    (Current frame)  *              | ...                       |  *    0(%esp) ->| variable size             |  *              |---------------------------|  */                                                                         See sys/stack.h 


We can explore the stack frames from Section 14.2.4.

> ffffffff866f1878::walk thread |::print kthread_t t_lwp->lwp_regs|::print "struct regs" r_rsp |=X                 8047d54         fecc9f80        febbac08        fea9df78         fe99df78 fe89df78           fe79df78                 fe69df78        fe59df78        fe49df78        fe39df58         fe29df58 fe19df58           fe09df58                 fdf9df58        fde9df58        fdd9df58        fdc9df58         fdb9df58 fda9df58           fd99df58                    fd89d538         fd79bc08 


> 8047d54/X 0x8047d54:      fedac74f > fedac74f/ libc.so.1'pause+0x67:           8e89c933        = xorl   %ecx,%ecx > febbac08/X 0xfebbac08:     feda83ec > feda83ec/ libc.so.1'_door_return+0xac:    eb14c483        = addl   $0x14,%esp > fea9df78/X 0xfea9df78:     fedabe4c > fedabe4c/ libc.so.1'_sleep+0x88:          8908c483        = addl   $0x8,%esp 


Thus, we observe user stacks of pause(), door_return(), and sleep(), as we expected.

14.3.2. Examining the Process Memory

In the process context, we can examine process memory as usual. For example, we can dissasemble instructions from a processes's address space:

> libc.so.1'_sleep+0x88::dis libc.so.1'_sleep+0x67:          pushq   $-0x13 libc.so.1'_sleep+0x69:          call    -0x5cb59 <0xfed4f2d4> libc.so.1'_sleep+0x6e:          addl    $0x4,%esp libc.so.1'_sleep+0x71:          movl    %esp,%eax libc.so.1'_sleep+0x73:          movl    %eax,0x22c(%rsi) libc.so.1'_sleep+0x79:          leal    0x14(%rsp),%eax libc.so.1'_sleep+0x7d:          pushq   %rax libc.so.1'_sleep+0x7e:          leal    0x10(%rsp),%eax libc.so.1'_sleep+0x82:          pushq   %rax libc.so.1'_sleep+0x83:          call    +0xc419  <0xfedb8260> libc.so.1'_sleep+0x88:          addl    $0x8,%esp libc.so.1'_sleep+0x8b:          movl    %edi,0x22c(%rsi) libc.so.1'_sleep+0x91:          movb    0xb3(%rsi),%cl libc.so.1'_sleep+0x97:          movb    %cl,0xb2(%rsi) libc.so.1'_sleep+0x9d:          jmp     +0x14    <libc.so.1'_sleep+0xb1> libc.so.1'_sleep+0x9f:          leal    0x14(%rsp),%eax libc.so.1'_sleep+0xa3:          pushq   %rax libc.so.1'_sleep+0xa4:          leal    0x10(%rsp),%eax libc.so.1'_sleep+0xa8:          pushq   %rax libc.so.1'_sleep+0xa9:          call    +0xc3f3  <0xfedb8260> libc.so.1'_sleep+0xae:          addl    $0x8,%esp 





Solaris Performance and Tools(c) Dtrace and Mdb Techniques for Solaris 10 and Opensolaris
Solaris Performance and Tools: DTrace and MDB Techniques for Solaris 10 and OpenSolaris
ISBN: 0131568191
EAN: 2147483647
Year: 2007
Pages: 180

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net