Chapter 4. Controlling dbx

This chapter describes features of dbx that affect its operation while debugging a program. Specifically, this chapter covers:

Creating and Removing dbx Variables

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” in Chapter 5, describes how to manipulate program variables.

Setting dbx Variables

The set command sets a dbx variable to a given value, defining the variable if it does not exist:

set var=exp

This command defines (or redefines) the specified dbx variable, setting its value to that of the expression you provide.

If you enter the set command without 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”

You can display the value of a variable by using the print command.

Example 4-1. set and print commands

(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: It is recommended 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.


Removing dbx Variables

The unset command removes a dbx variable.

Example 4-2. unset command

For example, to delete the $k variable, enter:

(dbx) unset $k


Using the History Feature and the History Editor

The dbx history feature is similar to the C shell's history feature; you can repeat commands that you have entered previously using this command. However, unlike the C shell's history feature, dbx does not allow you to execute a history command anywhere except at the beginning of a line. Also, dbx does not support history substitution of command arguments such as the C shell !$ argument.

Examining the History List

dbx stores all commands that you enter in the history list. The value of the dbx $lines variable determines how many commands are stored in the history list. The default value is 100.

You can display the history list by using the history command.

Example 4-3. history command

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


Repeating Commands

You can execute any of the commands contained in the history list. Each history command begins with an exclamation point (!). The following list describes history command usage:

  • !!: repeats the previous command. If the value of the dbx $repeatmode variable is set to 1, then entering a carriage return at an empty line is equivalent to executing !!. By default, $repeatmode is set to 0.

  • ! string: repeats the most recent command that starts with the specified string .

  • ! integer: repeats the command associated with the specified integer in the history list.

  • !- integer: repeats the command that occurred integer times before the most recent command. Entering !-1 executes the previous command, !-2 the command before that, and so forth.

Example 4-4. !! command

You can use the !! command to help you single-step through your program. (Single-stepping is described in “Stepping through Your Program” in Chapter 6.) 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);


Example 4-5. ! string command

Another easy 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 Chapter 5.) 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


Example 4-6. ! integer command

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

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 $editor variable to the name of an editor, the hed command invokes that editor. If you have not set this variable, dbx checks if the EDITOR environment variable is set, and if so, invokes that editor. If neither the dbx variable or the environment variable is set, dbx invokes the vi editor.

The syntax for the hed commands is:

hed [num1] [num1, num2 ] [all]

The following arguments are available:

  • hed (with no arguments): edits only the last line of the history list (the last command executed).

  • num1: edits line num1 in the history list.

  • num1, num2: edits the lines in the history list from num1 through num2.

  • all: edits the entire history list.

By default, dbx does not display the commands that it executes as a result of the hed command when the dbx $pimode variable is set to 0. If $pimode is set to 1, dbx displays the commands as it executes them. See Appendix C, “Predefined dbx Variables”, for more information.

Creating and Removing dbx Aliases

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” in Chapter 2, for more information on the .dbxinit file.

Creating Command Aliases

You can use the alias command to define new aliases:

alias name [command] ["string"] [arg1 ,...argN "string"]

The following arguments are available:

  • command: defines name as an alias for command.

  • string: defines name as an alias for the quoted string. With this form of the alias command, you can provide command arguments in the alias definition.

  • [arg1 ,... argN] “string“: defines name as an alias for the quoted string. arg1 through argN are arguments to the alias, appearing in the string definition. When you use the alias, you must provide values for the arguments, which dbx then substitutes in string.

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: for example, a is an alias for the assign command and 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.

Example 4-7. Creating and using aliases

If you want 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.

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


Example 4-8. Linked lists, aliases, and casts

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 for more information). 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
}


Listing Aliases

You can display the definition of aliases using the alias command:

alias [name]

The following arguments are available:

  • alias (with no arguments): lists all existing aliases.

  • name: lists the alias definition for name.

Example 4-9. Listing aliases

To display the definitions of the predefined aliases l and bp, enter:

(dbx) alias l
"list"
(dbx) alias bp
"stop in"


Removing Aliases

The unalias command removes the alias you provide as an argument.

Example 4-10. Removing aliases

To remove the pa alias defined in Example 4-7, enter the following command:

(dbx) unalias pa

You can remove any of the predefined dbx aliases; however, these aliases are restored the next time you start dbx.

Recording and Playing Back dbx Input and Output

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.

Recording Input

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 playback input or pi commands to execute again all the commands saved to the file. See “Playing Back Input”, for details.

Example 4-11. Recording input

To save the recorded input in a file called script, enter the following command:

(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 $defaultin variable . You can display the temporary filename by 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.

Ending a Recording Session

To end input or output recording sessions, use the unrecord command.

The following is the syntax of this command:

unrecord session1 [,session2...] [all]

The following arguments are available:

  • session1,[ session2]: turns off the specified recording session(s) and closes the file(s) involved.

  • all: turns off all recording sessions and closes all files involved.

Example 4-12. Ending a recording session

To stop recording session 4, enter the following dbx command:

(dbx) unrecord 4

To stop all recording sessions, enter:

(dbx) unrecord all

The dbx status command does not report on recording sessions. To see if any active recording sessions exist, use the record command described in “Examining the Record State”.

Playing Back Input

Use the playback input command to execute commands that you recorded with the record input command. Two aliases exist for the playback input command: pi and source. If you do not specify a filename, dbx uses the current temporary file that it created for the record input command.

If you set the dbx $pimode variable to nonzero, commands are printed out as they are played back. By default, $pimode is set to zero.

Recording Output

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 $rimode variable 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, when printing a large structure). Within dbx, you can use the playback output command (described in “Playing 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)).

Example 4-13. Recording output

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


Playing Output

The playback output command displays output saved with the record output command. This command works the same as the cat(1) command. If you do not specify a filename, dbx uses the current temporary file created for the record output command.

Example 4-14. Playing output

For example,t o display the output stored in the file script , enter:

(dbx) playback output script


Examining the Record State

The record command displays all record input and record output sessions currently active.

Example 4-15. Examining the record state

The following is an example of the record command used to display the record sessions:

(dbx) record
[4] record input /usr/demo/script (12 lines)
[5] record output /tmp/dbxoXa17992 (5 lines)


Executing dbx Scripts

You can create dbx command scripts by using an external editor and then executing these scripts by 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 pound sign (#) to introduce a comment. To include a # operator (described in “Operators” in Chapter 5) 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.