Debugging using DBX

Tags: debugging

A good starting guide for dbx

The Sun Studio 12: Debugging a Program With dbx documentation is a good starting guide for dbx. It provides basic instructions on starting dbx. It also talks about,

  • examining core file
  • setting breakpoints
  • stepping through the program
  • examining variables

Like some other debuggers great thing about dbx is that it knows which instructions refer to which line in original source-code. It has information not only on the execution/machine instructions but also where they do come from in the source of the program.

From the starting guide here is an example,

(dbx) list main
4    *
5    * the main function here returns void
6    */
7
8   void main () {
9     int a = 10;
10   }

Index of the documention guide helps to navigate easier. Sun Studio 12.2: Debugging a Program With dbx is probably the latst documentation for dbx. The studio 11 doc contains the an earlier version of the doc.

Basic Examples

The mentioned guide above shows nicely how to use dbx. However, I am going to provide some examples which might also be very useful for debugging assembly programs. As we have seen the regular commands such as list etc. relates to the lines in origin C/C++ sourcecode. My exmaples below will include commands which are helpful for debugging assembly programs.

We can apparently use the dis command to display to show machine instructions of a binary executable. Here is an example,

$ dis `which cat`
disassembly for /usr/bin/cat


section .text
_start()
    _start:                 bc 10 20 00  clr       %fp
    _start+0x4:             93 41 40 00  rd        %pc, %o1
    _start+0x8:             15 00 04 0a  sethi     %hi(0x102800), %o2
    _start+0xc:             94 02 a3 3c  add       %o2, 0x33c, %o2
    _start+0x10:            ba 02 80 09  add       %o2, %o1, %i5
    _start+0x14:            e0 5b a8 7f  ldx       [%sp + 0x87f], %l0
..... .... [and so on] .... ...... 

We run our example binary created using C++ using dbx,

/opt/SUNWspro/bin/dbx p01_example

Setting Breakpoint

Then, we set a breakpoint on the main funciton,

(dbx) stop in main

We run the program,

(dbx) run
Running: p01_example
(process id 71337)
stopped in main at line 9 in file "p01_example.c"
    9     int a = 10;

At a point, we can see status of our program in debugger dbx,

(dbx) status
 (2) stop in main

Listing Assembly Instructions

We can list the surrounding assembly instructions of program counter,

(dbx) listi
    9     int a = 10;
0x0000000100000a40: main       :        save     %sp, -192, %sp
0x0000000100000a44: main+0x0004:        mov      10, %l0
0x0000000100000a48: main+0x0008:        st       %l0, [%fp + 2043]
   10   }
0x0000000100000a4c: main+0x000c:        ret
0x0000000100000a50: main+0x0010:        restore

We can list the assembly instructions in the main function of our program using following,

(dbx) listi main
    9     int a = 10;
0x0000000100000a40: main       :        save     %sp, -192, %sp
0x0000000100000a44: main+0x0004:        mov      10, %l0
0x0000000100000a48: main+0x0008:        st       %l0, [%fp + 2043]
   10   }
0x0000000100000a4c: main+0x000c:        ret
0x0000000100000a50: main+0x0010:        restore

stack frame, thread etc

We can have a look at current lwp,

(dbx) lwp
current LWP ($lwp) is l@1

We can see, in which instruction our debugger is at,

(dbx) whereami
stopped in main at line 9 in file "p01_example.c"
    9     int a = 10;

Stepping through instructions

This is how step through each assembly instruction,

(dbx) stepi
stopped in main at 0x0000000100000a48
0x0000000100000a48: main+0x0008:        st       %l0, [%fp + 2043]

This is really useful to debug assembly programs.

Observing Registers

Here are examples of checking for register contents for example, SP, FP, PC, NPC, CWP, PSR, WIM

(dbx) x $SP
0x0000000100000a54: main+0x0014:         0x00010000

(dbx) x $FP
0x0000000100000a58: _init       :        0x9de3bf50

(dbx) x $PC
0x0000000100000a4c: main+0x000c:         0x81c7e008
(dbx) x $NPC
0x0000000100000a50: main+0x0010:         0x81e80000
(dbx) x $CWP
0x0000000100000a54: main+0x0014:         0x00010000

(dbx) x $PSR
0x0000000100000ad8: _init       :        0x9de3bf50

(dbx) x $WIM
0x0000000100000adc: _init+0x0004:        0x01000000

To display all registers we use,

(dbx) regs
current frame:  [1]
g0-g1    0x0000000000000000 0xffffffff7eff980c
g2-g3    0x0000000000000000 0x0000000000000000
g4-g5    0x0000000000000000 0x00000000000000ff
g6-g7    0x0000000000000000 0xffffffff7f7c2a40
o0-o1    0x0000000000000000 0x0000000000000000
o2-o3    0xffffffff7f22f400 0xffffffff7f7c2a40
o4-o5    0x0000000000000000 0x0000000000000000
o6-o7    0xffffffff7ffff081 0xffffffff7eff9830
l0-l1    0x000000000000000a 0x000000007f515800
l2-l3    0x0000000000000000 0xffffffff7f231c80
l4-l5    0xffffffff7f22f400 0x0000000000002880
l6-l7    0x0000000000002800 0xffffffff7f742df0
i0-i1    0x0000000000000001 0xffffffff7ffff9f8
i2-i3    0xffffffff7ffffa08 0x0000000000000000
i4-i5    0x0000000000000000 0x0000000000000000
i6-i7    0xffffffff7ffff141 0x0000000100000a08
y        0x0000000000000000
ccr      0x0000000000000044
pc       0x0000000100000a48:main+0x8    st       %l0, [%fp + 2043]
npc      0x0000000100000a4c:main+0xc    ret

Some of these might be useful in inspecting sparc register window.

Observing stack trace/ call frames

To move around the calls, observing the stack trace Chapter 7 - Using the Call Stack provides useful info. To display the current frame number,

(dbx) frame
1

To display current stack trace just like gdb we use,

(dbx) where

References

  1. Sun Studio 12: Debugging a Program With dbx
  2. dbx Command Summary
  3. dbx Command Reference

Comments