This chapter describes features of dbx that affect its operation while debugging a program. Specifically, this chapter covers:
dbx allows you to define variables that you can use within dbx to store values. These variables exist entirely in dbx; they are not part of your program. You can use dbx variables for a variety of purposes while debugging. For example, you can use dbx variables as temporary storage, counters, or pointers that you use to step through arrays.
dbx also provides many predefined variables that control how various dbx commands function. Appendix C, "Predefined dbx Variables" provides a complete list of predefined dbx variables and their purposes.
A dbx variable does not have a fixed type. You can assign a dbx variable any type of value, even if it already has a value of a different type. However, a variable predefined by dbx does have a fixed predefined type.
You can use almost any name for dbx variables. A good practice to follow is to use a dollar sign ($) as the first character of all dbx variables to prevent conflicts with most program variable names. All of dbx's predefined variables begin with a dollar sign.
The commands described in this section apply only to the manipulations of dbx variables, not program variables. "Displaying and Changing Program Variables" describes how to manipulate program variables.
The set command sets a dbx variable to a given value, defining the variable if it does not exist:
set var = exp | Define (or redefine) the specified dbx variable, setting its value to that of the expression you provide. |
You can display the value of a variable with the print command. For example:
(dbx) set $k = 1 (dbx) print $k 1 (dbx) set $k = $k +23 (dbx) print $k 24 (dbx) print $k / 11 2 |
In the above example, dbx performs an integer division because both the variable $k and the constant 11 are integers. If you assign a floating point value to $k and evaluate the expression again, dbx performs a floating point division:
(dbx) set $k = 24.0 (dbx) print $k 24.0 (dbx) print $k / 11 2.1818181818181817 |
Note: We recommend that you begin a dbx variable with a $ to avoid confusion with a program variable. A dbx variable without a leading $ hides any program variable that has the same name. The only way to see the program variable is to remove the dbx variable with an unset command. |
If you enter the set command without providing any arguments, dbx displays (in alphabetical order) a list of all currently defined dbx variables, including predefined variables. Partial output looks like this:
(dbx) set $addrfmt "0x%x" $addrfmt64 "0x%llx" $assignverify 1 $casesense 2 $ctypenames 1 $curevent 3 $curline 44 $curpc 268439708 ... $stacktracelimit 1024 $stdc 0 $stepintoall 0 $tagfile "tags" |
The dbx history feature is similar to the C shell's history feature in that it allows you to repeat commands that you have entered previously. However, unlike the C shell's history feature, dbx does not allow you to execute a history command anywhere except the beginning of a line. Also, dbx does not support history substitution of command arguments such as the C shell !$ argument.
dbx stores all commands that you enter in the history list. The value of the dbx variable $lines determines how many commands are stored in the history list. The default value is 100.
Display the history list with the history command. For example, after setting a breakpoint, running a program, and examining some variables, your history list might look something like this:
(dbx) history 1 set $prompt = "(dbx)" 2 set $page=0 3 set $pimode=1 4 stop in main 5 history |
You can execute any of the commands contained in the history list. Each history command begins with an exclamation point (!):
You can use the !! command to facilitate single-stepping through your program. (Single-stepping is described in "Stepping Through Your Program".) The following illustrates using the next command to execute 5 lines of source code and then using the !! command to repeat the next command.
For example:
(dbx) next 5 Process 22545 (test) stopped at [main:60 ,0x10001150] 60 total += j; (dbx) !! (!! = next 5) Process 22545 (test) stopped at [main:65 ,0x100011a0] 65 printf("i = %d, j = %d, total = %d\n",i,j,total); |
Another convenient way to repeat a commonly used command is with !string. For example, suppose that you occasionally print the values of certain variables using the printf command while running your program under dbx. (The printf command is described in "Printing Expressions".) In this case, as long as you do not enter any command beginning with "pr" after you enter the printf command, you can repeat the printf command by entering !pr. For example:
(dbx) printf "i = %d, j = %d, total = %d\n", i, j, total i = 4, j = 25, total = 1 ... (dbx) !pr i = 12, j = 272, total = 529 |
Using !integer, you can repeat any command in the history list. If you want to repeat the printf command, but you have entered a subsequent print command, examine the history list and then explicitly repeat the printf command using its reference number. For example:
(dbx) history 1 set $prompt = "(dbx)" 2 set $page=0 ... 45 printf "i = %d, j = %d, total = %d\n", i, j, total 46 next ... 49 print j ... 53 history (dbx) !45 (!45 = printf "i = %d, j = %d, total = %d\n", i, j, total) i = 9, j = 43, total = 1084 |
The history editor, hed, lets you use your favorite editor on any or all of the commands in the current dbx history list. When you enter the hed command, dbx copies all or part of the history list into a temporary file that you can edit. When you quit the editor, any commands left in this temporary file are automatically executed by dbx.
If you have set the dbx variable $editor to the name of an editor, the hed command invokes that editor. If you have not set the dbx variable $editor, dbx checks whether you have set the environment variable EDITOR and, if so, invokes that editor. If you have not set either the dbx variable or the environment variable, dbx invokes the vi editor.
The syntax for the hed commands is:
By default, dbx doesn't display the commands that it executes as a result of the hed command (the dbx variable $pimode is set to 0). If $pimode is set to 1, dbx displays the commands as it executes them. See $pimode in Appendix C, "Predefined dbx Variables" for more information.
You can create dbx aliases for debugger commands. Use these aliases as you would any other dbx command. When dbx encounters an alias, it expands the alias using the definition you provided.
dbx has a group of predefined aliases that you can modify or delete. These aliases are listed and described in Appendix B, "Predefined Aliases."
If you find that you often create the same aliases in your debugging sessions, you can include their definitions in your .dbxinit file so that they are automatically defined for you. See "Automatically Executing Commands on Startup" for more information on the .dbxinit file.
You can display the definition of aliases using the alias command:
For example, to display the definitions of the predefined aliases "l" and "bp," enter:
(dbx) alias l "list" (dbx) alias bp "stop in" |
You can use the alias command to define new aliases:
The simplest form of an alias is to redefine a dbx command with a short alias. Many of the predefined dbx aliases fall into this category: "a" is an alias for the assign command, "s" is an alias for the step command. When you use one of these aliases, dbx simply replaces it with the command for which it is an alias. Any arguments that you include on the command line are passed to the command.
For example, if you to create "gf" as an alias for the givenfile command, enter:
(dbx) alias gf givenfile (dbx) alias gf "givenfile" (dbx) gf Current givenfile is test (dbx) gf test2 Process 22545 (test) terminated Executable /usr/var/tmp/dbx_examples/test2 (dbx) gf Current givenfile is test2 |
More complex alias definitions require more than the name of a command. In these cases, you must enclose the entire alias definition string in double quotation marks. For example, you can define a brief alias to print the value of a variable that you commonly examine. Note that you must use the escape character (\) to include the double quotation marks as part of the alias definition. For example:
(dbx) alias pa "print \"a =\", a" (dbx) alias pa "print "a =", a" (dbx) pa a = 3 |
You can also define an alias so that you can pass arguments to it, much in the same way that you can provide arguments in a C language macro definition. When you use the alias, you must include the arguments. dbx then substitutes the values that you provide in the alias definition.
To illustrate this, consider the following alias definition:
(dbx) alias p(arg1, arg2, arg3, arg4) "print '|arg1|arg2|arg3|arg4|'" (dbx) alias p (arg1, arg2, arg3, arg4)"print '|arg1|arg2|arg3|arg4|'" |
The "p" alias takes four arguments and prints them surrounded by vertical bars (|). For example:
(dbx) p(1,2,3,4) |1|2|3|4| (dbx) p( first, second, 3rd,4) | first| second| 3rd|4| |
In the previous example, dbx retains any spaces that you enter when calling an alias.
You can also omit arguments when calling an alias as long as you include the commas as argument separators in the alias call:
(dbx) p(a,,b,c) |a||b|c| (dbx) p(,first missing, preceding space,) ||first missing| preceding space|| (dbx) delete delete |
The unalias command removes the alias you provide as an argument. For example, to remove the "pa" alias defined in the previous section, enter:
(dbx) unalias pa |
You can remove any of the predefined dbx aliases; however, these aliases are restored the next time you start dbx.
One way to follow linked lists is to use aliases and casts, another is to use the duel command (See "Using the High-Level Debugging Language duel" in Chapter 5). This example shows how to construct an alias that follows a simple linked list with members defined by the following structure:
struct list { struct list *next; int value; }; |
In this example, a dbx variable called $p is used as a pointer to a member of the linked list. You can define an alias called "foll" to print the contents of the list member to which $p currently points and then advance to the next list member. Because the command is too long to fit onto one line, this example uses the backslash character (\) to continue the command on a second line:
(dbx) alias foll "print *(struct list *)$p ; \ set $p = (long)((struct list *)($p))->next" |
Casting $p to an integer type when following the link (the second assignment in the alias) is essential. If omitted, dbx may leave the $p reference symbolic and if so, goes into an infinite loop. (Type Ctrl-c to interrupt dbx if it gets into the infinite loop.)
Before using this alias, you must set $p to point at the first list member. In this example, assume that the program variable top points to the first list member. Then you can use the "foll" alias to follow the linked list, printing the contents of each member as you proceed:
(dbx) set $p = top (dbx) foll struct list { next = 0x7fffc71c value = 57 } (dbx) foll struct list { next = 0x7fffc724 value = 3 } (dbx) foll struct list { next = 0x7fffc72c value = 12 } |
dbx allows you to play back your input and record dbx's output. dbx saves the information that you capture in files, which allows you to create command scripts that you can use in subsequent dbx sessions.
Use the record input command to start an input recording session. Once you start an input recording session, all commands to dbx are copied to the specified file. If the specified file already exists, dbx appends the input to the existing file. You can start and run as many simultaneous dbx input recording sessions as you need.
Each recording session is assigned a number when you begin it. Use this number to reference the recording session with the unrecord command described in "Ending a Recording Session".
After you end the input recording session, use the command file with the playbackinput or pi commands to execute again all the commands saved to the file. See "Playing Back Input".
For example, to save the recorded input in a file called script, enter:
(dbx) record input script [4] record input script (0 lines) |
If you do not specify a file to record input, dbx creates a temporary dbx file in the /tmp directory. The name of the temporary file is stored in the dbx variable $defaultin. You can display the temporary filename using the print command:
(dbx) print $defaultin |
Because the dbx temporary files are deleted at the end of the dbx session, use the temporary file to repeat previously executed dbx commands in the current debugging session only. If you need a command file for use in subsequent dbx sessions, you must specify the filename when you invoke record input. If the specified file exists, the new input is appended to the file.
To end input or output recording sessions, use the unrecord command.
unrecord session1 [, session2 ...] |
| |
unrecord all | Turns off all recording sessions and closes all files involved. |
For example, to stop recording session 4, enter the dbx command:
(dbx) unrecord 4 |
To stop all recording sessions, enter:
(dbx) unrecord all |
The dbxstatus command does not report on recording sessions. To see whether or not any active recording sessions exist, use the record command described in "Examining the Record State".
Use playback input to execute commands that you recorded with the record input command. Two aliases exist for playback input: pi and source.) If you don't specify a filename, dbx uses the current temporary file that it created for the record input command. If you set the dbx variable $pimode to nonzero, the commands are printed out as they are played back. By default, $pimode is set to zero.
Use the record output command to start output recording sessions within dbx. During an output recording session, dbx copies its screen output to a file. If the specified file already exists, dbx appends to the existing file. You can start and run as many simultaneous dbx output recording sessions as you need.
By default, the commands you enter are not copied to the output file; however, if you set the dbx variable $rimode to a nonzero value, dbx also copies the commands you enter.
Each recording session is assigned a number when you begin it. Use this number to reference the recording session with the unrecord command described in "Ending a Recording Session".
The record output command is very useful when the screen output is too large for a single screen (for example, printing a large structure). Within dbx, you can use the playback output command (described in "Playing Back Output") to look at the recorded information. After quitting dbx, you can review the output file using any IRIX system text viewing command (such as vi(1)).
For example, to record the dbx output in a file called gaffa, enter:
(dbx) record output gaffa |
To record both the commands and the output, enter:
(dbx) set $rimode=1 (dbx) record output gaffa |
If you omit the filename, dbx saves the recorded output in a temporary file in /tmp. The temporary file is deleted at the end of the dbx session. To save output for use after the dbx session, you must specify the filename when giving the record output command. The name of the temporary file is stored in the dbx variable $defaultout.
To display the temporary filename, type:
(dbx) print $defaultout |
The playback output command displays output saved with the record output command. This command works the same as the cat(1) command. If you don't specify a filename, dbx uses the current temporary file created for the record output command.
For example, to display the output stored in the file script, enter:
(dbx) playback output script |
You can create dbx command scripts using an external editor and then execute these scripts using the pi or playback input command. This is a convenient method for creating and executing automated test scripts.
You can include comments in your command scripts by using a single pound sign (#) to introduce a comment. To include a # operator (described in "Operators") in a dbx script, use two pound signs (for example, ##27). When dbx sees a pound sign in a script file, it interprets all characters between the pound sign and the end of the current line as a comment.