HP OpenVMS Systems Documentation
OpenVMS Debugger Manual
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:
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:
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.
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:
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:
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:
1Note that MACRO-32 must be compiled with the AMACRO compiler.
On Integrity server processors, the SET LANGUAGE command takes the following keywords:
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).
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
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.
Several debugger commands and constructs evaluate language expressions:
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:
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
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:
For some languages (like Pascal and Ada) the specific array declaration
determines how the array is based.
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:
220.127.116.11 Initialization Code
Many programs issue a NOTATMAIN message when a program is brought under debugger control. For example:
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.
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:
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:
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:
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:
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.
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:
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:
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:
At this exception breakpoint, entering a STEP command enables you to step directly into condition handler SSHAND:
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.