OpenVMS Debugger Manual


Previous Contents Index

  1. The /DEBUG qualifier on the DCL FORTRAN command directs the compiler to write the symbol information associated with SQUARES into the object module, SQUARES.OBJ, in addition to the code and data for the program.
    The /NOOPTIMIZE qualifier disables optimization by the Fortran compiler, which ensures that the executable code matches the source code of the program. Debugging optimized code can be confusing because the contents of some program locations might be inconsistent with what you would expect from viewing the source code.
  2. The /DEBUG qualifier on the DCL command LINK causes the linker to include all symbol information that is contained in SQUARES.OBJ in the executable image.
  3. The DCL command DEBUG/KEEP starts the debugger, which displays its banner and the debugger prompt, DBG>. You can now enter debugger commands.
  4. The debugger command RUN SQUARES brings the program SQUARES under debugger control. The informational message identifies the source language of the program and the name of the main program unit (FORTRAN and SQUARES, respectively, in this example).
    Execution is initially paused at the start of the main program unit (line 1 of SQUARES, in this example).
  5. You decide to test the values of variables N and K after the READ statement has been executed and the value 0 has been assigned to K.
    The command STEP 4 executes 4 source lines of the program. Execution is now paused at line 9. Note that the STEP command ignores source lines that do not result in executable code; also, by default, the debugger identifies the source line at which execution is paused.
  6. The command EXAMINE N, K displays the current values of N and K. Their values are correct at this point in the execution of the program.
  7. The command STEP 2 executes the program into the loop that copies and squares all nonzero elements of INARR into OUTARR.
  8. The command EXAMINE I,K displays the current values of I and K.
    I has the expected value 1, but K has the value 0 instead of 1, which is the expected value. Now you can see the error in the program: K should be incremented in the loop just before it is used in line 11.
  9. The DEPOSIT command assigns K the value it should have now: 1.
  10. The SET TRACE command is now used to patch the program so that the value of K is incremented automatically in the loop. The command sets a tracepoint that triggers every time execution reaches line 11:
  11. To test the patch, the GO command starts execution from the current location.
    The program output shows that the patched program works properly. The EXITSTATUS message shows that the program executed to completion.
  12. The SPAWN command spawns a subprocess to return control temporarily to DCL level (without ending the debugging session) so that you can correct the source file and recompile and relink the program.
  13. The EDIT command invokes an editor and the source file is edited to addK = K + 1 after line 10, as shown. (Compiler-assigned line numbers have been added to clarify the example.)
  14. The revised program is compiled and linked.
  15. The LOGOUT command terminates the spawned subprocess and returns control to the debugger.
  16. The (debugger) command RUN SQUARES brings the revised program under debugger control so that its correct execution can be verified.
  17. The SET BREAK command sets a breakpoint that triggers every time line 12 is executed. The DO clause displays the values of I and K automatically when the breakpoint triggers.
  18. The GO command starts execution.
    At the first breakpoint, the value of K is 1, indicating that the program is running correctly so far. Each additional GO command shows the current values of I and K. After two more GO commands, K is now 3, as expected, but note that I is 4. The reason is that one of the INARR elements was 0 so that lines 11 and 12 were not executed (and K was not incremented) for that iteration of the DO loop. This confirms that the program is running correctly.
  19. The EXIT command ends the debugging session and returns control to DCL level.


Chapter 3
Controlling and Monitoring Program Execution

This chapter describes how to control and monitor program execution while debugging by using the following techniques:

The following related functions are discussed in Chapter 2:

This chapter includes information that is common to all programs. For more information:

For information about rerunning your program or running another program from the current debugging session, see Section 1.3.3 and Section 1.3.4.

3.1 Commands Used to Execute the Program

Only four debugger commands are directly associated with program execution:

GO
STEP
CALL
EXIT (if your program has exit handlers)

As explained in Section 2.3.1 and Section 2.3.2, GO and STEP are the basic commands for starting and resuming program execution. The STEP command is discussed further in Section 3.2.

During a debugging session, routines are executed as they are called during the execution of a program. The CALL command enables you to arbitrarily call and execute a routine that was linked with your program. This command is discussed in Section 13.7.

The EXIT command was discussed in Section 1.8, in conjunction with ending a debugging session. Because it executes any exit handlers in your program, it is also useful for debugging exit handlers (see Section 14.6).

When using any of these four commands, note that program execution can be interrupted or stopped by any of the following events:

3.2 Executing the Program by Step Unit

The STEP command (probably the most frequently used debugger command) enables you to execute your program in small increments called step units.

By default, a step unit is an executable 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 next line to be executed:


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 of module TEST. Line 27 is in COUNT, a routine within module TEST.

The STEP command can also execute several source lines at a time. If you specify a positive integer as a parameter, the STEP command executes that number of lines. In the following example, the STEP command executes the next three lines:


DBG> STEP 3
stepped to TEST\COUNT\%LINE 34 
     34:   SWAP(X,Y);
DBG>

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. Also, if a line has more than one statement on it, the debugger executes all the statements on that line as part of the single step.

Source lines are displayed by default after stepping if they are available for the module being debugged. Source lines are not available if you are stepping in code that has not been compiled or linked with the /DEBUG qualifier (for example, a shareable image routine). If source lines are available, you can control their display with the SET STEP [NO]SOURCE command and the /[NO]SOURCE qualifier of the STEP command. For information about how to control the display of source code in general and in particular after stepping, see Chapter 6.

3.2.1 Changing the STEP Command Behavior

You can change the default behavior of the STEP command in two ways:

In the following example, the STEP/INTO command steps into a called routine when the program counter (PC) is at a call statement. The debugger displays the source line identifying the routine PRODUCT, which is called from routine COUNT of module TEST:


DBG> STEP/INTO
stepped to routine TEST\PRODUCT 
     6:    function PRODUCT(X,Y : INTEGER) return INTEGER is 
DBG>

After the STEP/INTO command executes, subsequent STEP commands revert to the default behavior.

In contrast, the SET STEP command enables you to establish new defaults for the STEP command. These defaults remain in effect until another SET STEP command is entered. For example, the SET STEP INTO command causes subsequent STEP commands to behave like STEP/INTO (SET STEP LINE causes subsequent STEP commands to behave like STEP/LINE).

There is a SET STEP command parameter for each STEP command qualifier.

You can override the current STEP command defaults for the duration of a single STEP command by specifying other qualifiers. Use the SHOW STEP command to identify the current STEP command defaults.

3.2.2 Stepping Into and Over Routines

By default, when the PC is at a call statement and you enter the STEP command, the debugger steps over the called routine. Although the routine is executed, execution is not paused within the routine but, rather, on the beginning of the line that follows the call statement. When stepping by instruction, execution is paused on the instruction that follows a called routine's return instruction.

To step into a called routine when the PC is at a call statement, enter the STEP/INTO command. The following example shows how to step into the routine PRODUCT, which is called from routine COUNT of module TEST:


DBG> STEP
stepped to TEST\COUNT\%LINE 18 
    18:       AREA := PRODUCT(LENGTH, WIDTH); 
DBG> STEP/INTO
stepped to routine TEST\PRODUCT 
     6:    function PRODUCT(X,Y : INTEGER) return INTEGER is 
DBG>

To return to the calling routine from any point within the called routine, use the STEP/RETURN command. It causes the debugger to step to the return instruction of the routine being executed. A subsequent STEP command brings you back to the statement that follows the routine call. For example:


DBG> STEP/RETURN
stepped on return from TEST\PRODUCT\%LINE 11 to TEST\PRODUCT\%LINE 15+4 
    15:    end PRODUCT; 
DBG> STEP
stepped to TEST\COUNT\%LINE 19 
    19:       LENGTH := LENGTH + 1; 
DBG>

To step into several routines, enter the SET STEP INTO command to change the default behavior of the STEP command from STEP/OVER to STEP/INTO:


DBG> SET STEP INTO

As a result of this command, when the PC is at a call statement, a STEP command suspends execution within the called routine. If you later want to step over routine calls, enter the SET STEP OVER command.

When SET STEP INTO is in effect, you can qualify the kinds of called routines that the debugger is stepping into by specifying any of the following parameters with the SET STEP command:

These parameters make it possible to step into application-defined routines and automatically step over system routines, and so on. For example, the following command directs the debugger to step into called routines in user space only. The debugger steps over routines in system space and in shareable images.


DBG> SET STEP INTO,NOSYSTEM,NOSHARE

3.3 Suspending and Tracing Execution with Breakpoints and Tracepoints

This section discusses using the SET BREAK and SET TRACE commands to, respectively, suspend and trace program execution. The commands are discussed together because of their similarities.

SET BREAK Command Overview

The SET BREAK command lets you specify program locations or events at which to suspend program execution (breakpoints). After setting a breakpoint, you can start or resume program execution with the GO command, letting the program run until the specified location or condition is reached. When the breakpoint is triggered, the debugger suspends execution, identifies the breakpoint, and displays the DBG> prompt. You can then enter debugger commands---for example, to determine where you are (with the SHOW CALLS command), step into a routine, examine or modify variables, and so on.

The syntax of the SET BREAK command is as follows:


SET BREAK[/qualifier[...]] [address-expression[, ...]] 
    [WHEN (conditional-expression)] 
    [DO (command[; ...])] 

The following example shows a typical use of the SET BREAK command and shows the general default behavior of the debugger at a breakpoint.

In this 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) where execution is paused, and prompts for another command:


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

SET TRACE Command Overview

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

The debugger's default behavior at a tracepoint is identical to that at a breakpoint, except that program execution continues past a tracepoint. Thus, the DBG> prompt is not displayed when a tracepoint is reached and announced by the debugger.

Except for the command name, the syntax of the SET TRACE command is identical to that of the SET BREAK command:


 
SET TRACE[/qualifier[...]] [address-expression[, ...]] 
[WHEN (conditional-expression)] 
[DO (command[; ...])] 

The SET TRACE and SET BREAK commands have similar syntax. When using the SET TRACE command, specify address expressions, qualifiers, and the optional WHEN and DO clauses exactly as with the SET BREAK command.

Unless you use the /TEMPORARY qualifier on the SET BREAK or SET TRACE command, breakpoints and tracepoints remain in effect until you:

To identify all of the breakpoints or tracepoints that are currently set, use the SHOW BREAK or SHOW TRACE command.

To deactivate, activate, or cancel breakpoints or tracepoints, use the following commands (see Section 3.3.7):

DEACTIVATE BREAK, DEACTIVATE TRACE
ACTIVATE BREAK, ACTIVATE TRACE
CANCEL BREAK, CANCEL TRACE

The following sections describe how to specify program locations and events with the SET BREAK and SET TRACE commands.

3.3.1 Setting Breakpoints or Tracepoints on Individual Program Locations

To set a breakpoint or a tracepoint on a particular program location, specify an address expression with the SET BREAK or SET TRACE command.

Fundamentally, an address expression specifies a memory address or a register. Because the debugger understands the symbols associated with your program, the address expressions you typically use with the SET BREAK or SET TRACE command are routine names, labels, or source line numbers rather than memory addresses---the debugger converts these symbols to addresses.

3.3.1.1 Specifying Symbolic Addresses

Note

In some cases, when using the SET BREAK or SET TRACE command with a symbolic address expression, you might need to set a module or specify a scope or a path name. Those concepts are described in detail in Chapter 5. The examples in this section assume that all modules are set and that all symbols referenced are uniquely defined, unless otherwise indicated.

The following examples show how to set a breakpoint on a routine (SWAP) and a tracepoint on a label (LOOP1):


DBG> SET BREAK SWAP
DBG> SET TRACE LOOP1

The next command sets a breakpoint on the return instruction of routine SWAP. Breaking on the return instruction of a routine lets you inspect the local environment (for example, to obtain the values of local variables) while the routine is still active.


DBG> SET BREAK/RETURN SWAP

Some languages, for example Fortran, use numeric labels. To set a breakpoint or a tracepoint on a numeric label, you must precede the number with the built-in symbol %LABEL. Otherwise, the debugger interprets the number as a memory address. For example, the following command sets a tracepoint on label 20:


DBG> SET TRACE %LABEL 20

You can set a breakpoint or a tracepoint on a line of source code by specifying the line number preceded by the built-in symbol %LINE. The following command sets a breakpoint on line 14:


DBG> SET BREAK %LINE 14

The previous breakpoint causes execution to pause on the first instruction of line 14. You can set a breakpoint or a tracepoint only on lines for which the compiler generated instructions (lines that resulted in executable code). If you specify a line number that is not associated with an instruction, such as a comment line or a statement that declares but does not initialize a variable, the debugger issues a diagnostic message. For example:


DBG> SET BREAK %LINE 6
%DEBUG-I-LINEINFO, no line 6, previous line is 5, next line is 8
%DEBUG-E-NOSYMBOL, symbol '%LINE 6' is not in the symbol table
DBG>

The previous messages indicate that the compiler did not generate instructions for lines 6 or 7 in this case.

Some languages allow more than one statement on a line. In such cases, you can use statement numbers to differentiate among statements on the same line. A statement number consists of a line number, followed by a period (.), and a number indicating the statement. The syntax is as follows:


%LINE line-number.statement-number

For example, the following command sets a tracepoint on the second statement of line 38:


DBG> SET TRACE %LINE 38.2

When searching for symbols that you reference in commands, the debugger uses the conventions described in Section 5.3.1. That is, it first looks within the module where execution is currently paused, then in other scopes associated with routines on the call stack, and so on. Therefore, to specify a symbol that is defined in more than one module, such as a line number, you might need to use a path name. For example, the following command sets a tracepoint on line 27 of module MOD4:


DBG> SET TRACE MOD4\%LINE 27

Remember the symbol lookup conventions when specifying a line number in debugger commands. If that line number is not defined in the module where execution is paused (because it is not associated with an instruction), the debugger uses the symbol lookup conventions to locate another module where the line number is defined.

When specifying address expressions, you can combine symbolic addresses with byte offsets. Thus, you can set a breakpoint or a tracepoint on a particular instruction by specifying its line number and the byte offset from the beginning of that line to the first byte of the instruction. For example, the next command sets a breakpoint on the address that is five bytes beyond the beginning of line 23:


DBG> SET BREAK %LINE 23+5


Previous Next Contents Index