Monday, June 10, 2013

dbx - Universal Debugger in Unix/Linux

More Advanced Information: http://www-rohan.sdsu.edu/doc/dbx.html

DBX:


The Program

/* debug.c */ 
#include  

void printit(int j)
{ 
   printf("%i\n", j);
} 

void main()
{
 int i=0;

 for (i=0; i >= 0; i++)
 {
  printit(i);
 }
}

This program obviously has an infinite loop problem. But let's say that we were at a loss of what to do about it, and that we wanted the computer to stop at 10. We first start up dbx:

blue 1% dbx debug 
dbx version 3.19 Nov 3 1994 19:59:46 
Executable /Net/deimos/great-space/math/johnsond/debug
(dbx)

First of all,
(dbx) help 
gives us a listing of the commands that we will, in all likelihood, use.

Example:

(dbx) run
0 
1
2 
3 
4 
5 
6 
7 
8 
9 
10
...


Obviously, we wish to alter the program so that the computer stops at 10. To stop an infinite loop, press [Ctrl-C] If debug took arguments, you would place them after 'run'. This command can be shortened by simply typing 'r' at the dbx prompt; this will also activate any arguments that you called the last time 'run' was used.
First, we place a stop in the main after the initialization of the variables.
Breaking Point:
(dbx) list 
>*  12 {
    13   int i=0; 
    14   for (i=0; i >= 00; i++)
    15   {
    16    printit(i); 
    17   }
    18 }
(dbx) 
By calling 'list', the computer proceeds to print out the main with its line numbers appended to it. By adding the name of a procedure/function as an argument right after 'list', dbx will list the code starting at that particular procedure.
We know the initialization happens at line 13, so we put a stop right after the initialization.
(dbx) stop at 14 
Process 701: [3] stop at "/Net/deimos/great-space/math/johnsond/debug.c":14
(dbx) 
We now run the program:
(dbx) run 
Process 701 (debug) started
[3] Process 701 (debug) stopped at [main:14 ,0x400a5c]
  14 for (i=0; i >= 00; i++)
(dbx)
We now want to trace the variable i:
(dbx) trace i 
Process 701: [4] trace i in main 
(dbx)
Just for kicks, it might be nice to also trace when a certain procedure (i.e. printit) is being called:
(dbx) trace printit 
Process 701: [5] trace printit 
(dbx)
It is also possible to trace a variable within a procedure; in fact, this is the only way that you can see variable changes of a non-main variable:
(dbx) trace j in printit 
Process 701: [6] trace j in printit 
(dbx)
Now that we have put a trace on almost every concievable thing that we can trace and have placed a stop in the middle of the program, let's quickly examine what stops, traces, and traps have been set:
(dbx) status 
Process 701: [3] stop at "/Net/deimos/great-space/math/johnsond/debug.c":14
Process 701: [4] trace i in main 
Process 701: [5] trace printit 
Process 701: [6] trace j in printit 
(dbx)
Notice how each seperate stop or trace has a number that pertains to it inside the brackets. Now, let's continue through the program to see what's wrong with debug.c...
(dbx) step 
Process 701 (debug) stopped at [main:16 ,0x400a60]
  16 printit(i);  
(dbx)
Single-stepping can be done with either the command 'step' or 's'. It is also possible to step a certain number of times at once by entering 'step [# of times]':
(dbx) step 2 
[5] calling printit(j = 0) from function main 
0
Process 701 (debug) stopped at [printit:9 ,0x400a28]
  9  }
(dbx)
We have moved two steps through the program. Trace [5] has been sprung, which checks for when the procedure 'printit' has called, and so the computer outputs which function called it.
Instead of single stepping, it is also possible to simply continue until either a certain procedure is called or until a certain line number is come to. First, let us simply let the computer continue the program for a time:
<continue>
(dbx) cont

[5] printit returning from printit 
[4] i changed before [main: line 14]: 
                new value = 1;  
[5] calling printit(j = 1) from function main
1
[5] printit returning from printit 
[4] i changed before [main: line 14]: 
  old value = 1;
                new value = 2;  
[5] calling printit(j = 2) from function main
2
[5] printit returning from printit 
[4] i changed before [main: line 14]: 
  old value = 2;
                new value = 3;  
[5] calling printit(j = 3) from function main
3

...

[5] printit returning from printit 
[4] i changed before [main: line 14]: 
  old value = 7
                new value = 8;  
[5] calling printit(j = 8) from function main
8
More (n if no)?n
(dbx) 
One would think that a command such as cont in this situation would go ad nauseum. In fact, it simply halts after a time and asks whether to continue or not. To continue until a procedure is next called, you must first exit that procedure and then call cont in [proc], unless there is a call to the procedure within itself:
(dbx) cont in printit
[5] calling printit(j = 0) from function main
   8 printf("%i\n", j); 
(dbx) 
There is also a 'cont' command that allows you to continue until a certain line number:
(dbx) cont to 16
  16 printit(i); 
(dbx) 
Finally, after using all of these tools, one will finally be able to find the problem in the code for 'debug.c'. To finish the job, type:
(dbx) quit
Process   701 (debug) terminated
blue 2%

No comments:

Post a Comment