[OpenVMS documentation]
[Site home] [Send comments] [Help with this site] [How to order documentation] [OpenVMS site] [Compaq site]
Updated: 11 December 1998

OpenVMS Debugger Manual


Previous Contents Index

2.3 Controlling and Monitoring Program Execution

This section explains how to perform the following tasks:

With this information you can pick program locations where you can then test and manipulate the contents of variables as described in Section 2.4.

2.3.1 Starting or Resuming Program Execution

Use the GO command to start or resume program execution.

After it is started with the GO command, program execution continues until one of the following events occurs:

With most programming languages, when you bring a program under debugger control, execution is initially paused directly at the beginning of the main program. Entering a GO command at this point quickly enables you to test for an infinite loop or an exception.

If an infinite loop occurs during execution, the program does not terminate, so the debugger prompt does not reappear. To obtain the prompt, interrupt execution by pressing Ctrl/C (see Section 1.4). If you are using screen mode, the pointer in the source display indicates where execution stopped. You can also use the SHOW CALLS command to identify the currently active routine calls on the call stack (see Section 2.3.3).

If an exception that is not handled by your program is signaled, the debugger interrupts execution at that point so that you can enter commands. You can then look at the source display and a SHOW CALLS display to find where execution is paused.

The most common use of the GO command is in conjunction with breakpoints, tracepoints, and watchpoints, as described in Section 2.3.4, Section 2.3.5, and Section 2.3.6, respectively. If you set a breakpoint in the path of execution and then enter the GO command, execution is paused at that breakpoint. Similarly, if you set a tracepoint, execution is monitored through that tracepoint. If you set a watchpoint, execution is paused when the value of the watched variable changes.

2.3.2 Executing the Program by Step Unit

Use the STEP command to execute the program one or more step units at a time.

By default, a step unit is one line of source code. In the following example, the STEP command executes one line, reports the action ("stepped to..."), and displays the line number (27) and source code of the line to be executed next:


DBG> STEP
stepped to TEST\COUNT\%LINE 27 
     27:   X := X + 1;
DBG>

Execution is now paused at the first machine-code instruction for line 27 within routine COUNT of module TEST.

When displaying a program symbol (for example, a line number, routine name, or variable name), the debugger always uses a path name. A path name consists of the symbol plus a prefix that identifies the symbol's location. In the previous example, the path name is TEST\COUNT\%LINE 27. The leftmost element of a path name is the module name. Moving toward the right, the path name lists any successively nested routines and blocks that enclose the symbol. A backslash character (\) is used to separate elements (except when the language is Ada, where a period is used to parallel Ada syntax).

A path name uniquely identifies a symbol of your program to the debugger. In general, you need to use path names in commands only if the debugger cannot resolve a symbol ambiguity in your program (see Section 2.5). Usually the debugger can determine the symbol you mean from its context.

When using the STEP command, note that only those source lines for which code instructions were generated by the compiler are recognized as executable lines by the debugger. The debugger skips over any other lines---for example, comment lines.

You can specify different stepping modes, such as stepping by instruction rather than by line (SET STEP INSTRUCTION). Also, by default, the debugger steps over called routines---execution is not paused within a called routine, although the routine is executed. By entering the SET STEP INTO command, you direct the debugger to suspend execution within called routines as well as within the routine in which execution is currently paused (SET STEP OVER is the default mode).

2.3.3 Determining Where Execution Is Paused

Use the SHOW CALLS command when you are unsure where execution is paused during a debugging session (for example, after a Ctrl/C interruption).

The command displays a traceback that lists the sequence of calls leading to the routine in which execution is paused. For each routine (beginning with the one in which execution is paused), the debugger displays the following information:

For example:


DBG> SHOW CALLS
 module name   routine name   line    rel PC    abs PC 
 
*TEST           PRODUCT        18    00000009  0000063C 
*TEST           COUNT          47    00000009  00000647 
*MY_PROG        MY_PROG        21    0000000D  00000653
DBG>

This example indicates that execution is paused at line 18 of routine PRODUCT (in module TEST), which was called from line 47 of routine COUNT (in module TEST), which was called from line 21 of routine MY_PROG (in module MY_PROG).

2.3.4 Suspending Program Execution with Breakpoints

The SET BREAK command enables you to select locations at which to suspend program execution (breakpoints). You can then enter commands to check the call stack, examine the current values of variables, and so on. You resume execution from a breakpoint with the GO or STEP commands.

The following example shows a typical use of the SET BREAK command:


DBG> SET BREAK COUNT
DBG> GO
   .
   .
   .
break at routine PROG2\COUNT 
     54:  procedure COUNT(X,Y:INTEGER);
DBG>

In the example, the SET BREAK command sets a breakpoint on routine COUNT (at the beginning of the routine's code); the GO command starts execution; when routine COUNT is encountered, execution is paused, the debugger announces that the breakpoint at COUNT has been reached ("break at ..."), displays the source line (54) at which execution is paused, and prompts for another command. At this breakpoint, you can use the STEP command to step through routine COUNT and then use the EXAMINE command (discussed in Section 2.4.1) to check on the values of X and Y.

When using the SET BREAK command, you can specify program locations using various kinds of address expressions (for example, line numbers, routine names, memory addresses, byte offsets). With high-level languages, you typically use routine names, labels, or line numbers, possibly with path names to ensure uniqueness.

Routine names and labels should be specified as they appear in the source code. Line numbers can be derived from either a source code display or a listing file. When specifying a line number, use the prefix %LINE. Otherwise, the debugger interprets the line number as a memory location. For example, the following command sets a breakpoint at line 41 of the module in which execution is paused. The breakpoint causes the debugger to suspend execution at the beginning of line 41.


DBG> SET BREAK %LINE 41

Note that you can set breakpoints only on lines that resulted in machine-code instructions. The debugger warns you if you try to do otherwise (for example, on a comment line). To pick a line number in a module other than the one in which execution is paused, you must specify the module's name in a path name. For example:


DBG> SET BREAK SCREEN_IO\%LINE 58

You can also use the SET BREAK command with a qualifier, but no parameter, to break on every line, or on every CALL instruction, and so on. For example:


DBG> SET BREAK/LINE
DBG> SET BREAK/CALL

You can set breakpoints on events, such as exceptions, or state transitions in tasking programs.

You can conditionalize a breakpoint (with a WHEN clause) or specify that a list of commands be executed at the breakpoint (with a DO clause).

To display the current breakpoints, enter the SHOW BREAK command.

To deactivate a breakpoint, enter the DEACTIVATE BREAK command, and specify the program location exactly as you did when setting the breakpoint. This causes the debugger to ignore the breakpoint during program execution. However, you can activate it at a later time, for example, when you rerun the program (see Section 1.3.3). A deactivated breakpoint is listed as such in a SHOW BREAK display.

To activate a breakpoint, use the ACTIVATE BREAK command. Activating a breakpoint causes it to take effect during program execution.

The commands DEACTIVATE BREAK/ALL and ACTIVATE BREAK/ALL operate on all breakpoints and are particularly useful when rerunning a program.

To cancel a breakpoint, use the CANCEL BREAK command. A canceled breakpoint is no longer listed in a SHOW BREAK display.

2.3.5 Tracing Program Execution with Tracepoints

The SET TRACE command enables you to select locations for tracing the execution of your program (tracepoints), without stopping its execution. After setting a tracepoint, you can start execution with the GO command and then monitor the path of execution, checking for unexpected behavior. By setting a tracepoint on a routine, you can also monitor the number of times it is called.

As with breakpoints, every time a tracepoint is reached, the debugger issues a message and displays the source line. But the program continues executing, and the debugger prompt is not displayed. For example:


DBG> SET TRACE COUNT
DBG> GO
trace at routine PROG2\COUNT 
     54:  procedure COUNT(X,Y:INTEGER);
   .
   .
   .

This is the only difference between a breakpoint and a tracepoint. When using the SET TRACE command, you specify address expressions, qualifiers, and optional clauses exactly as with the SET BREAK command. The commands SHOW TRACE, ACTIVATE TRACE, DEACTIVATE TRACE, and CANCEL TRACE operate on tracepoints in a manner similar to the corresponding commands for breakpoints (see Section 2.3.4).

2.3.6 Monitoring Changes in Variables with Watchpoints

The SET WATCH command enables you to specify program variables that the debugger monitors as your program executes. This process is called setting watchpoints. If the program modifies the value of a watched variable, the debugger suspends execution and displays information. The debugger monitors watchpoints continuously during program execution. (Note that you can also use the SET WATCH command to monitor arbitrary program locations, not just variables.)

The technique you use to set watchpoints depends on your system (VAX or Alpha) and the type of variable (static or nonstatic).

On VAX processors, you can set a watchpoint on a static variable by specifying the variable's names with the SET WATCH command. Since a static variable is associated with the same memory address throughout program execution, this variable name is always meaningful. For example, the following command sets a watchpoint on the variable TOTAL:


DBG> SET WATCH TOTAL

Subsequently, every time the program modifies the value of TOTAL, the watchpoint is triggered.

The following example shows what happens when your program modifies the contents of this watched variable:


DBG> SET WATCH TOTAL
DBG> GO
   .
   .
   .
watch of SCREEN_IO\TOTAL at SCREEN_IO\%LINE 13 
     13:   TOTAL = TOTAL + 1; 
    old value: 16 
    new value: 17 
break at SCREEN_IO\%LINE 14 
     14:   POP(TOTAL);
DBG>

In this example, a watchpoint is set on the variable TOTAL and execution is started. When the value of TOTAL changes, execution is paused. The debugger announces the event ("watch of..."), identifying where TOTAL changed (the beginning of line 13) and the associated source line. The debugger then displays the old and new values and announces that execution has been paused at the beginning of the next line (14). Finally, the debugger prompts for another command. When a change in a variable occurs at a point other than the beginning of a source line, the debugger gives the line number plus the byte offset from the beginning of the line.

On VAX processors and Alpha processors, you can set a watchpoint on a nonstatic variable by setting a tracepoint on the defining routine and specifying a DO clause to set the watchpoint whenever execution reaches the tracepoint. Since a nonstatic variable is allocated on the stack or in a register and exists only when its defining routine is active (on the call stack), the variable name is not always meaningful in the way that a static variable name is.

In the following example, a watchpoint is set on the nonstatic variable Y in routine ROUT3. After the tracepoint is triggered, the WPTTRACE message indicates that the nonstatic watchpoint is set, and the watchpoint is triggered when the value of Y changes. For example:


DBG> SET TRACE/NOSOURCE ROUT3 DO (SET WATCH Y)
DBG> GO
   .
   .
   .
trace at routine MOD4\ROUT3
%DEBUG-I-WPTTRACE, nonstatic watchpoint, tracing every 
                   instruction
   .
   .
   .
watch of MOD4\ROUT3\Y at MOD4\ROUT3\%LINE 16
   16:     Y := 4
   old value:    3
   new value:    4
break at MOD4\ROUT3\%LINE 17
   17:     SWAP(X,Y);
DBG>

When execution returns to the calling routine, the nonstatic variable is no longer active, so the debugger automatically cancels the watchpoint and issues a message to that effect.

On Alpha processors, the debugger treats all watchpoints as nonstaticwatchpoints.

The commands SHOW WATCH, ACTIVATE WATCH, DEACTIVATE WATCH, and CANCEL WATCH operate on watchpoints in a manner similar to the corresponding commands for breakpoints (see Section 2.3.4). However, a nonstatic watchpoint exists only as long as execution remains within the scope of the variable being watched.

2.4 Examining and Manipulating Program Data

This section explains how to use the EXAMINE, DEPOSIT, and EVALUATE commands to display and modify the contents of variables and evaluate expressions. Before you can examine or deposit into a nonstatic variable, as defined in Section 2.3.6, its defining routine must be active.

2.4.1 Displaying the Value of a Variable

To display the current value of a variable, use the EXAMINE command. It has the following syntax:


EXAMINE address-expression

The debugger recognizes the compiler-generated data type of the variable you specify and retrieves and formats the data accordingly. The following examples show some uses of the EXAMINE command.

Examine a string variable:


DBG> EXAMINE EMPLOYEE_NAME
PAYROLL\EMPLOYEE_NAME:    "Peter C. Lombardi"
DBG>

Examine three integer variables:


DBG> EXAMINE WIDTH, LENGTH, AREA
SIZE\WIDTH:   4 
SIZE\LENGTH:  7 
SIZE\AREA:   28
DBG>

Examine a two-dimensional array of real numbers (three per dimension):


DBG> EXAMINE REAL_ARRAY
PROG2\REAL_ARRAY 
   (1,1):       27.01000 
   (1,2):       31.00000 
   (1,3):       12.48000 
   (2,1):       15.08000 
   (2,2):       22.30000 
   (2,3):       18.73000
DBG>

Examine element 4 of a one-dimensional array of characters:


DBG> EXAMINE CHAR_ARRAY(4)
PROG2\CHAR_ARRAY(4): 'm'
DBG>

Examine a record variable (COBOL example):


DBG> EXAMINE PART
INVENTORY\PART: 
    ITEM:     "WF-1247" 
    PRICE:     49.95 
    IN_STOCK:  24
DBG>

Examine a record component (COBOL example):


DBG> EXAMINE IN_STOCK OF PART
INVENTORY\IN-STOCK of PART: 
    IN_STOCK:  24
DBG>

You can use the EXAMINE command with any kind of address expression (not just a variable name) to display the contents of a program location. The debugger associates certain default data types with untyped locations. You can override the defaults for typed and untyped locations if you want the data interpreted and displayed in some other data format.

2.4.2 Assigning a Value to a Variable

To assign a new value to a variable, use the DEPOSIT command. It has the following syntax:


DEPOSIT address-expression = language-expression

The DEPOSIT command is like an assignment statement in most programming languages.

In the following examples, the DEPOSIT command assigns new values to different variables. The debugger checks that the value assigned, which can be a language expression, is consistent with the data type and dimensional constraints of the variable.

Deposit a string value (it must be enclosed in quotation marks (") or apostrophes ('):


DBG> DEPOSIT PART_NUMBER = "WG-7619.3-84"

Deposit an integer expression:


DBG> DEPOSIT WIDTH = CURRENT_WIDTH + 10

Deposit element 12 of an array of characters (you cannot deposit an entire array aggregate with a single DEPOSIT command, only an element):


DBG> DEPOSIT C_ARRAY(12) := 'K'

Deposit a record component (you cannot deposit an entire record aggregate with a single DEPOSIT command, only a component):


DBG> DEPOSIT EMPLOYEE.ZIPCODE = 02172

Deposit an out-of-bounds value (X was declared as a positive integer):


DBG> DEPOSIT X = -14
%DEBUG-I-IVALOUTBNDS, value assigned is out of bounds 
        at or near DEPOSIT

As with the EXAMINE command, you can specify any kind of address expression (not just a variable name) with the DEPOSIT command. You can override the defaults for typed and untyped locations if you want the data interpreted in some other data format.

2.4.3 Evaluating Language Expressions

To evaluate a language expression, use the EVALUATE command. It has the following syntax:


EVALUATE language-expression

The debugger recognizes the operators and expression syntax of the currently set language. In the following example, the value 45 is assigned to the integer variable WIDTH; the EVALUATE command then obtains the sum of the current value of WIDTH and 7:


DBG> DEPOSIT WIDTH := 45
DBG> EVALUATE WIDTH + 7
52
DBG>

In the next example, the values TRUE and FALSE are assigned to the Boolean variables WILLING and ABLE, respectively; the EVALUATE command then obtains the logical conjunction of these values:


DBG> DEPOSIT WILLING := TRUE
DBG> DEPOSIT ABLE := FALSE
DBG> EVALUATE WILLING AND ABLE
False
DBG>

2.5 Controlling Access to Symbols in Your Program

To have full access to the symbols that are associated with your program (variable names, routine names, source code, line numbers, and so on), you must compile and link the program using the /DEBUG qualifier, as explained in Section 1.2.

Under these conditions, the way in which the debugger handles these symbols is transparent to you in most cases. However, the following two areas might require action:

2.5.1 Setting and Canceling Modules

To facilitate symbol searches, the debugger loads symbol information from the executable image into a run-time symbol table (RST), where that information can be accessed efficiently. Unless symbol information is in the RST, the debugger does not recognize or properly interpret the associated symbols.

Because the RST takes up memory, the debugger loads it dynamically, anticipating what symbols you might want to reference in the course of program execution. The loading process is called module setting, because all symbol information for a given module is loaded into the RST at one time.

Initially, only the module containing the image transfer address is set. Subsequently, whenever execution of the program is interrupted, the debugger sets the module that contains the routine in which execution is paused. This enables you to reference the symbols that should be visible at that location.

If you try to reference a symbol in a module that has not been set, the debugger warns you that the symbol is not in the RST. For example:


DBG> EXAMINE K
%DEBUG-W-NOSYMBOL, symbol 'K' is not in symbol table
DBG>

You must use the SET MODULE command to set the module containing that symbol explicitly. For example:


DBG> SET MODULE MOD3
DBG> EXAMINE K
MOD3\ROUT2\K: 26
DBG>

The SHOW MODULE command lists the modules of your program and identifies which modules are set.

Dynamic module setting can slow the debugger down as more and more modules are set. If performance becomes a problem, you can use the CANCEL MODULE command to reduce the number of set modules, or you can disable dynamic module setting by entering the SET MODE NODYNAMIC command (SET MODE DYNAMIC enables dynamic module setting).


Previous Next Contents Index

[Site home] [Send comments] [Help with this site] [How to order documentation] [OpenVMS site] [Compaq site]
[OpenVMS documentation]

Copyright © Compaq Computer Corporation 1998. All rights reserved.

Legal
4538PRO_004.HTML