HP OpenVMS Systems Documentation

Content starts here

OpenVMS Debugger Manual

Previous Contents Index

14.2 Debugging Screen-Oriented Programs

The debugger uses the terminal screen for input and output (I/O) during a debugging session. If you use a single terminal to debug a screen-oriented program that uses most or all of the screen, debugger I/O can overwrite, or can be overwritten by, program I/O.

Using one terminal for both program I/O and debugger I/O is even more complicated if you are debugging in screen mode and your screen-oriented program calls any Run-Time Library (RTL) Screen Management (SMG$) routines. This is because the debugger's screen mode also calls SMG routines. In such cases, the debugger and your program share the same SMG pasteboard, which causes further interference.

To avoid these problems when debugging a screen-oriented program, use one of the following techniques to separate debugger I/O from program I/O:

  • If you are at a workstation running VWS, start your debugging session and then enter the debugger command SET MODE SEPARATE. It creates a separate terminal-emulator window for debugger I/O. Program I/O continues to be displayed in the window from which you started the debugger.
  • If you are at a workstation running Compaq DECwindows Motif:
    • To display the debugger's DECwindows Motif interface on a separate workstation (also running DECwindows Motif), see Section
    • To use the debugger's command interface rather than the DECwindows Motif interface, see Section It explains how to create a separate DECterm window for debugger I/O. The effect is similar to using the command SET MODE SEPARATE on a workstation running VWS.
  • If you do not have a workstation, use two terminals---one for program I/O and another for debugger I/O. This technique is described in the rest of this section.

Assume that TTD1: is your current terminal from which you plan to start the debugger. You want to display debugger I/O on terminal TTD2: so that TTD1: is devoted exclusively to program I/O.

Follow these steps:

  1. Provide the necessary protection to TTD2: so that you can allocate that terminal from TTD1: (see Section 14.2.1).
    The remaining steps are all performed from TTD1:.
  2. Allocate TTD2:. This provides your process on TTD1: with exclusive access to TTD2: as follows:

  3. Assign the debugger logical names DBG$INPUT and DBG$OUTPUT to TTD2: as follows:


    DBG$INPUT and DBG$OUTPUT specify the debugger input device and output device, respectively. By default, these logical names are equated to SYS$INPUT and SYS$OUTPUT, respectively. Assigning DBG$INPUT and DBG$OUTPUT to TTD2: enables you to display debugger commands and debugger output on TTD2:.
  4. Make sure that the terminal type is known to the system. Enter the following command:


    If the device type is unknown, your system manager (or a user with LOG_IO or PHY_IO privilege) must make it known to the system as shown in the following example. In the example, the terminal is assumed to be a VT200:

  5. Run the program to be debugged:

    DBG> RUN prog-name

    You can now observe debugger I/O on TTD2:
  6. When finished with the debugging session, deallocate TTD2: as follows (or log out):


14.2.1 Setting the Protection to Allocate a Terminal

On a properly secured system, terminals are protected so that you cannot allocate a terminal from another terminal.

To set the necessary protection, your system manager (or a user with the privileges indicated) should follow the steps shown in the following example.

In the example, TTD1: is your current terminal (from which you plan to start the debugger), and TTD2: is the terminal to be allocated so that it can display debugger I/O.

  1. If both TTD1: and TTD2: are hardwired to the system, go to Step 4.
    If TTD1: and TTD2: are connected to the system over a LAT (local area transport), go to Step 2.
  2. Log in to TTD2:.
  3. Enter these commands (you need LOG_IO or PHY_IO privilege):

  4. Enter one of the following commands (you need OPER privilege):

    1. The SET ACL command line is preferred because it uses an access control list (ACL). In the example, access is restricted to user identification code (UIC) [PROJ,JONES].
    2. The SET PROTECTION command line provides world read/write access, which allows any user to allocate and perform I/O to TTD2:.

14.3 Debugging Multilanguage Programs

The debugger enables you to debug modules whose source code is written in different languages within the same debugging session. This section highlights some language-specific behavior that you should be aware of to minimize possible confusion.

When debugging in any language, be sure to consult:

  • The debugger's online help (type HELP Language)
  • The documentation supplied with that language

14.3.1 Controlling the Current Debugger Language

When you bring a program under debugger control, the debugger sets the current language to that in which the module containing the main program (usually the routine containing the image transfer address) is written. The current language is identified at that point. For example:

           Debugger Banner and Version Number
DBG> RUN prog-name
Language: PASCAL, Module: FORMS

The current language setting determines how the debugger parses and interprets the names, operators, and expressions you specify in debugger commands, including things like the typing of variables, array and record syntax, the default radix for integer data, case sensitivity, and so on. The language setting also determines how the debugger displays data associated with your program.

Many programs include modules that are written in languages other than that of the main program. To minimize confusion, by default the debugger language remains set to the language of the main program throughout a debugging session, even if execution is paused within a module written in another language.

To take full advantage of symbolic debugging with such modules, use the SET LANGUAGE command to set the debugging context to that of another language. For example, the following command causes the debugger to interpret any symbols, expressions, and so on according to the rules of the COBOL language:


On Alpha processors, the SET LANGUAGE command takes the following keywords:

C++ COBOL Fortran MACRO-32 1
MACRO-64 Pascal PL/I  

1Note that MACRO-32 must be compiled with the AMACRO compiler.

On Integrity server processors, the SET LANGUAGE command takes the following keywords:

C++ COBOL Fortran MACRO-32 1
C++ COBOL Fortran MACRO-32 1

1Note that MACRO-32 must be compiled with the AMACRO compiler.
1Note that MACRO-32 must be compiled with the AMACRO compiler.

In addition, when debugging a program that is written in an unsupported language, you can specify the SET LANGUAGE UNKNOWN command. To maximize the usability of the debugger with unsupported languages, the SET LANGUAGE UNKNOWN command causes the debugger to accept a large set of data formats and operators, including some that might be specific to only a few supported languages. The operators and constructs that are recognized when the language is set to UNKNOWN are identified in the debugger's online help (type HELP Language).

14.3.2 Specific Differences Among Languages

This section lists some of the differences you should keep in mind when debugging in various languages. Included are differences that are affected by the SET LANGUAGE command and other differences (for example, language-specific initialization code and predefined breakpoints).

This section is not intended to be complete. See the debugger's online help (type HELP Language) and your language documentation for complete details. Default Radix

The default radix for entering and displaying integer data is decimal for most languages.

On Alpha processors, the exceptions are BLISS, MACRO--32, and MACRO--64, which have a hexadecimal default radix.

Use the SET RADIX command to establish a new default radix. Evaluating Language Expressions

Several debugger commands and constructs evaluate language expressions:

  • WHEN clauses, which are used with the SET BREAK, SET TRACE, and SET WATCH commands

When processing these commands, the debugger evaluates language expressions in the syntax of the current language and in the current radix as discussed in Section 4.1.6. At each execution (not when you enter the command), the debugger checks the syntax of any expressions in WHEN or DO clauses, and then evaluates them.

Note that operators vary widely among different languages. For example, the following two commands evaluate equivalent expressions in Pascal and Fortran, respectively:

DBG> SET WATCH X WHEN (Y < 5)       ! Pascal 

Assume that the language is set to Pascal and you have entered the first (Pascal) command. You now step into a Fortran routine, set the language to Fortran, and resume execution. While the language is set to Fortran, the debugger is not able to evaluate the expression (Y < 5). As a result, it sets an unconditional watchpoint and, when the watchpoint is triggered, returns a syntax error for the < operator.

This type of discrepancy can also occur if you use commands that evaluate language expressions in debugger command procedures and initialization files.

When the language is set to BLISS, the debugger processes language expressions that contain variable names (or other address expressions) differently than when it is set to another language. See Section 4.1.6 for details. Arrays and Records

The syntax for denoting array elements and record components (if applicable) varies among languages.

For example, some languages use brackets ([]), and others use parentheses (( )), to delimit array elements.

Some languages have zero-based arrays. Some languages have one-based arrays, as in the following example:

   (1,1):       27 
   (1,2):       31 
   (1,3):       12 
   (2,1):       15 
   (2,2):       22 
   (2,3):       18

For some languages (like Pascal and Ada) the specific array declaration determines how the array is based. Case Sensitivity

Names and language expressions are case sensitive in C. You must specify them exactly as they appear in the source code. For example, the following two commands are not equivalent when the language is set to C:

DBG> SET BREAK screen_io\%LINE 10 Initialization Code

Many programs issue a NOTATMAIN message when a program is brought under debugger control. For example:

           Debugger Banner and Version Number
DBG> RUN prog-name
Language: ADA, Module: MONITOR 
Type GO to reach main program

The NOTATMAIN message indicates that execution is paused before the beginning of the main program. This enables you to execute and check some initialization code under debugger control.

The initialization code is created by the compiler and is placed in a special PSECT named LIB$INITIALIZE. For example, in the case of an Ada package, the initialization code belongs to the package body (which might contain statements to initialize variables, and so on). In the case of a Fortran program, the initialization code declares the handler that is needed if you specify the /CHECK=UNDERFLOW or /CHECK=ALL qualifier.

The NOTATMAIN message indicates that, if you do not want to debug the initialization code, you can execute immediately to the beginning of the main program by entering a GO command. You are then at the same point as when you start debugging any other program. Entering the GO command again starts program execution. Predefined Breakpoints

If your program is a tasking program, two breakpoints that are associated with tasking exception events are automatically established when the program is brought under debugger control. These breakpoints are not affected by a SET LANGUAGE command. They are established automatically during debugger initialization when appropriate run-time libraries are present.

To identify these predefined breakpoints, enter the SHOW BREAK command. For example:

Predefined breakpoint on ADA event "EXCEPTION_TERMINATED" for any value 
Predefined breakpoint on ADA event "DEPENDENTS_EXCEPTION" for any value

14.4 Recovering from Stack Corruption

The debugger allocates a certain amount of memory at startup and shares the stack with the user's program. If a user process exception results in exhaustion of resources or corruption of the stack, the debugger may be incapable of regaining control, and the debug session may terminate.

Be aware of this potential behavior after the occurrence of stack corruption messages or warnings about continuing from a severe error. In either case, the integrity of the debug session cannot be guaranteed.

You should try one of the following measures:

  • Change your source code, temporarily or permanently, to reduce resource consumption or lessen the use of stack space
  • Increase quotas
  • Specify a larger stack size when linking your program

14.5 Debugging Exceptions and Condition Handlers

A condition handler is a procedure that the operating system executes when an exception occurs.

Exceptions include hardware conditions (such as an arithmetic overflow or a memory access violation) or signaled software exceptions (for example, an exception signaled because a file could not be found).

Operating system conventions specify how, and in what order, various condition handlers established by the operating system, the debugger, or your own program are invoked---for example, the primary handler, call frame (application-declared) handlers, and so on. Section 14.5.3 describes condition handling when you are using the debugger. See the OpenVMS Run-Time Library Routines Volume for additional general information about condition handling.

Tools for debugging exceptions and condition handlers include the following:

  • The SET BREAK/EXCEPTION and SET TRACE/EXCEPTION commands, which direct the debugger to treat any exception generated by your program as a breakpoint or tracepoint, respectively (see Section 14.5.1 and Section 14.5.2).
  • Several built-in symbols (such as %EXC_NAME), which enable you to qualify exception breakpoints and tracepoints (see Section 14.5.4).
  • The SET BREAK/EVENT and SET TRACE/EVENT commands, which enable you to break on or trace exception events that are specific to Ada, SCAN, or multithread programs (see the corresponding documentation for more information).

14.5.1 Setting Breakpoints or Tracepoints on Exceptions

When you enter a SET BREAK/EXCEPTION or SET TRACE/EXCEPTION command, you direct the debugger to treat any exception generated by your program as a breakpoint or tracepoint. As a result of a SET BREAK/EXCEPTION command, if your program generates an exception, the debugger suspends execution, reports the exception and the line where execution is paused, and prompts for commands. The following example shows the effect:

%SYSTEM-F-INTDIV, arithmetic trap, integer divide by zero at PC=0000066C, PSL=03C00022 
break on exception preceding TEST\%LINE 13 
     6:         X := 3/Y;

Note that an exception breakpoint (or tracepoint) is triggered even if your program has a condition handler to handle the exception. The SET BREAK/EXCEPTION command causes a breakpoint to occur before any handler can execute (and possibly dismiss the exception). Without the exception breakpoint, the handler will be executed, and the debugger would get control only if no handler dismissed the exception (see Section 14.5.2 and Section 14.5.3).

The following command line is useful for identifying where an exception occurred. It causes the debugger to automatically display the sequence of active calls and the PC value at an exception breakpoint:


You can also create a screen-mode DO display that issues a SHOW CALLS command whenever the debugger interrupts execution. For example:


An exception tracepoint (established with the SET TRACE/EXCEPTION command) is like an exception breakpoint followed by a GO command without an address expression specified.

An exception breakpoint cancels an exception tracepoint, and vice versa.

To cancel exception breakpoints or tracepoints, use the CANCEL BREAK/EXCEPTION or CANCEL TRACE/EXCEPTION command, respectively.

14.5.2 Resuming Execution at an Exception Breakpoint

When an exception breakpoint is triggered, execution is paused before any application-declared condition handler is invoked. When you resume execution from the breakpoint with the GO, STEP, or CALL commands, the behavior is as follows:

  • Entering a GO command without an address-expression parameter, or entering a STEP command, causes the debugger to resignal the exception. The GO command enables you to observe which application-declared handler, if any, next handles the exception. The STEP command causes you to step into that handler (see the next example).
  • Entering a GO command with an address-expression parameter causes execution to resume at the specified location, which inhibits the execution of any application-declared handlers.
  • A common debugging technique at an exception breakpoint is to call a dump routine with the CALL command (see Chapter 13). When you enter the CALL command at an exception breakpoint, no breakpoints, tracepoints, or watchpoints that were previously set within the called routine are active, so that the debugger does not lose the exception context. After the routine has executed, the debugger prompts for input. Entering a GO or STEP command at this point causes the debugger to resignal the exception.

The following Fortran example shows how to determine the presence of a condition handler at an exception breakpoint and how a STEP command, entered at the breakpoint, enables you to step into the handler.

At the exception breakpoint, the SHOW CALLS command indicates that the exception was generated during a call to routine SYS$QIOW:

%SYSTEM-F-SSFAIL, system service failure exception, status=0000013C, PC=7FFEDE06, PSL=03C00000 
break on exception preceding SYS$QIOW+6
module name  routine name       line       rel PC    abs PC 
              SYS$QIOW                         00000006  7FFEDE06 
*EXC$MAIN     EXC$MAIN            23      0000003B  0000063B

On VAX processors, the following SHOW STACK command indicates that no handler is declared in routine SYS$QIOW. However, one level down the call stack, routine EXC$MAIN has declared a handler named SSHAND:

stack frame 0 (2146296644) 
    condition handler: 0 
       SPA:            0 
       S:              0 
       mask:           ^M<R2,R3,R4,R5,R6,R7,R8,R9,R10,R11> 
       PSW:            0020 (hexadecimal) 
    saved AP:          2146296780 
    saved FP:          2146296704 
    saved PC:          EXC$MAIN\%LINE 25
stack frame 1 (2146296704) 
    condition handler: SSHAND 
       SPA:            0 
       S:              0 
       mask:           ^M<R11> 
       PSW:            0000 (hexadecimal) 
    saved AP:          2146296780 
    saved FP:          2146296760 
    saved PC:          SHARE$DEBUG+2217

At this exception breakpoint, entering a STEP command enables you to step directly into condition handler SSHAND:

stepped to routine SSHAND 
 module name  routine name    line     rel PC    abs PC 
*SSHAND       SSHAND            2    00000002  00000642 
----- above condition handler called with exception 0000045C: 
%SYSTEM-F-SSFAIL, system service failure exception, status=0000013C, PC=7FFEDE06, PSL=03C00000 
----- end of exception message 
              SYS$QIOW                 00000006  7FFEDE06 
*EXC$MAIN     EXC$MAIN         23      0000003B  0000063B

The debugger symbolizes the addresses of condition handlers into names if that is possible. However, note that with some languages, exceptions are first handled by a Run-Time Library (RTL) routine, before any application-declared condition handler is invoked. In such cases, the address of the first condition handler might be symbolized to an offset from an RTL shareable image address.

Previous Next Contents Index