|
HP OpenVMS systems documentation |
Previous | Contents | Index |
Symbol ambiguities can occur when a symbol (for example, a variable name X) is defined in more than one routine or other program unit.
In most cases, the debugger resolves symbol ambiguities automatically, by using the scope and visibility rules of the currently set language and the ordering of routine calls on the call stack, as explained in Section 5.3.1.
However, in some cases the debugger might respond as follows when you specify a symbol that is defined multiple times:
DBG> EXAMINE X %DEBUG-W-NOUNIQUE, symbol 'X' is not unique DBG> |
To resolve such problems, you must specify a scope where the debugger should search for a particular declaration of the symbol. In the following example, the pathname COUNTER\X uniquely specifies a particular declaration of X:
DBG> EXAMINE COUNTER\X COUNTER\X: 14 DBG> |
The following sections discuss scope concepts and explain how to
resolve symbol ambiguities.
5.3.1 Symbol Lookup Conventions
This section explains how the debugger searches for symbols, resolving most potential symbol ambiguities using the scope and visibility rules of the programming language and also its own rules. Section 5.3.2 and Section 5.3.3 describe supplementary techniques that you can use when necessary.
You can specify symbols in debugger commands by using either a path name or the exact symbol.
If you use a path name, the debugger looks for the symbol in the scope denoted by the pathname prefix (see Section 5.3.2).
If you do not specify a pathname prefix, by default, the debugger searches the run-time symbol table (RST) as explained in the following paragraphs (you can modify this default behavior with the SET SCOPE command as explained in Section 5.3.3).
First, the debugger looks for symbols in the PC scope (also known as scope 0), according to the scope and visibility rules of the currently set language. This means that, typically, the debugger first looks within the block or routine surrounding the current PC value (where execution is currently paused). If the symbol is not found, the debugger searches the nesting program unit, then its nesting unit, and so on. The precise manner, which depends on the language, ensures that the correct declaration of a symbol that is defined multiple times is chosen.
However, you can reference symbols throughout your program, not just those that are visible in the PC scope as defined by the language. This is necessary so you can set breakpoints in arbitrary areas, examine arbitrary variables, and so on. Therefore, if the symbol is not visible in the PC scope, the debugger continues searching as follows.
After the PC scope, the debugger searches the scope of the calling routine (if any), then its caller, and so on. Symbolically, the complete scope search list is denoted (0,1,2,...,n), where 0 denotes the PC scope and n is the number of calls on the call stack. Within each scope (call frame), the debugger uses the visibility rules of the language to locate a symbol.
This search list, based on the call stack, enables the debugger to differentiate symbols that are defined multiple times in a convenient, predictable way.
If the symbol is still not found, the debugger searches the rest of the RST---that is, the other set modules and the global symbol table (GST). At this point the debugger does not attempt to resolve any symbol ambiguities. Instead, if more than one occurrence of the symbol is found, the debugger issues a message such as the following:
%DEBUG-W-NOUNIQUE, symbol 'Y' is not unique |
If you have used a SET SCOPE command to modify the default symbol
search behavior, you can restore the default behavior with the CANCEL
SCOPE command.
5.3.2 Using SHOW SYMBOL and Path Names to Specify Symbols Uniquely
If the debugger indicates that a symbol reference is not unique, use the SHOW SYMBOL command to obtain all possible path names for that symbol, then specify a path name to reference the symbol uniquely. For example:
DBG> EXAMINE COUNT %DEBUG-W-NOUNIQUE, symbol 'COUNT' is not unique DBG> SHOW SYMBOL COUNT data MOD7\ROUT3\BLOCK1\COUNT data MOD4\ROUT2\COUNT routine MOD2\ROUT1\ROUT3\COUNT DBG> EXAMINE MOD4\ROUT2\COUNT MOD4\ROUT2\COUNT: 12 DBG> |
The command SHOW SYMBOL COUNT lists all declarations of the symbol COUNT that exist in the RST. The first two declarations of COUNT are variables (data). The last declaration listed is a routine. Each declaration is shown with its pathname prefix, which indicates the path (search scope) the debugger must follow to reach that particular declaration. For example, MOD4\ROUT2\COUNT denotes the declaration of the symbol COUNT in routine ROUT2 of module MOD4.
The pathname format is as follows. The leftmost element of a path name identifies the module containing the symbol. Moving toward the right, the path name lists the successively nested routines and blocks that lead to the particular declaration of the symbol (which is the rightmost element).
The debugger always displays symbols with their path names, but you need to use path names in debugger commands only to resolve an ambiguity.
The debugger looks up line numbers like any other symbols you specify (by default, it first looks in the module where execution is paused). A common use of path names is for specifying a line number in an arbitrary module. For example:
DBG> SET BREAK QUEUE_MANAGER\%LINE 26 |
The SHOW SYMBOL command identifies global symbols twice, because global symbols are included both in the DST and in the GST. For example:
DBG> SHOW SYMBOL X data ALPHA\X ! global X data ALPHA\BETA\X ! local X data X (global) ! same as ALPHA\X DBG> |
In the case of a shareable image, its global symbols are universal
symbols and the SHOW SYMBOL command identifies universal symbols twice
(see Section 5.1.2 and Section 5.4).
5.3.2.1 Simplifying Path Names
Path names are often long. You can simplify the process of specifying path names in three ways:
To abbreviate a path name, delete the names of nesting program units starting from the left, but leave enough of the path name to specify it uniquely. For example, ROUT3\COUNT is a valid abbreviated path name for the routine in the first example of Section 5.3.2.
To define a symbol for a path name, use the DEFINE command. For example:
DBG> DEFINE INTX = INT_STACK\CHECK\X DBG> EXAMINE INTX |
To set a new search scope, use the SET SCOPE command, which is
described in Section 5.3.3.
5.3.2.2 Specifying Symbols in Routines on the Call Stack
You can use a numeric path name to specify the scope associated with a routine on the call stack (as identified in a SHOW CALLS display). The pathname prefix "0\" denotes the PC scope, the pathname prefix "1\" denotes scope 1 (the scope of the caller routine), and so on.
For example, the following commands display the current values of two distinct declarations of Y, which are visible in scope 0 and scope 2, respectively:
DBG> EXAMINE 0\Y DBG> EXAMINE 2\Y |
By default, the EXAMINE Y command signifies EXAMINE 0\Y.
See the SET SCOPE/CURRENT command description in Section 5.3.3. That
command enables you to reset the reference for the default scope search
list relative to the call stack.
5.3.2.3 Specifying Global Symbols
To specify a global symbol uniquely, use a backslash (\) as a prefix to the symbol. For example, the following command displays the value of the global symbol X:
DBG> EXAMINE \X |
When a routine is called recursively, you might need to distinguish among several calls to the same routine, all of which generate new symbols with identical names.
You can include an invocation number in a path name to indicate a particular call to a routine. The number must be a nonnegative integer and must follow the name of the rightmost routine in the path name. A 0 denotes the most recent invocation; 1 denotes the previous invocation, and so on. For example, if PROG calls COMPUTE and COMPUTE calls itself recursively, and each call creates a new variable SUM, the following command displays the value of SUM for the most recent call to COMPUTE:
DBG> EXAMINE PROG\COMPUTE 0\SUM |
To refer to the variable SUM that was generated in the previous call to COMPUTE, express the path name with a 1 in place of the 0.
When you do not include an invocation number, the debugger assumes that the reference is to the most recent call to the routine (the default invocation number is 0).
See the SET SCOPE/CURRENT command description in Section 5.3.3. That
command enables you to reset the reference for the default scope search
list relative to the call stack.
5.3.3 Using SET SCOPE to Specify a Symbol Search Scope
By default, the debugger looks up symbols that you specify without a pathname prefix by using the scope search list described in Section 5.3.1.
The SET SCOPE command enables you to establish a new scope for symbol lookup so that you do not have to use a path name when referencing symbols in that scope.
In the following example, the SET SCOPE command establishes the path name MOD4\ROUT2 as the new scope for symbol lookup. Then, references to Y without a pathname prefix specify the declaration of Y that is visible in the new scope.
DBG> EXAMINE Y %DEBUG-E-NOUNIQUE, symbol 'Y' is not unique DBG> SHOW SYMBOL Y data MOD7\ROUT3\BLOCK1\Y data MOD4\ROUT2\Y DBG> SET SCOPE MOD4\ROUT2 DBG> EXAMINE Y MOD4\ROUT2\Y: 12 DBG> |
After you enter a SET SCOPE command, the debugger applies the path name you specified in the command to all references that are not individually qualified with path names.
You can specify numeric path names with SET SCOPE. For example, the following command sets the current scope to be three calls down from the PC scope:
DBG> SET SCOPE 3 |
You can also define a scope search list to specify the order in which the debugger should search for symbols. For example, the following command causes the debugger to look for symbols first in the PC scope (scope 0) and then in the scope denoted by routine ROUT2 of module MOD4:
DBG> SET SCOPE 0, MOD4\ROUT2 |
The debugger's default scope search list is equivalent to entering the following command (if it existed):
DBG> SET SCOPE 0,1,2,3,...,n |
Here the debugger searches successively down the call stack to find a symbol.
You can use the SET SCOPE/CURRENT command to reset the reference for the default scope search list to another routine down the call stack. For example, the following command sets the scope search list to be 2,3,4,...,n:
DBG> SET SCOPE/CURRENT 2 |
To display the current scope search list for symbol lookup, use the
SHOW SCOPE command. To restore the default scope search list (see
Section 5.3.1), use the CANCEL SCOPE command.
5.4 Debugging Shareable Images
By default, your program might be linked with several Compaq-supplied shareable images (for example, the run-time library image LIBRTL.EXE). This section explains how to extend the concepts described in the previous sections when debugging user-defined shareable images.
A shareable image is not intended to be directly executed. A shareable image must first be included as input in the linking of an executable image, and then the shareable image is loaded at run time when the executable image is run. You do not have to install a shareable image to debug it. Instead, you can debug your own private copy by assigning a logical name to it.
See the HP OpenVMS Linker Utility Manual for detailed information about linking shareable
images.
5.4.1 Compiling and Linking Shareable Images for Debugging
The basic steps in compiling and linking a shareable image for debugging are as follows:
These steps are shown next with a simple example. In the example, MAIN.FOR and SUB1.FOR are the source files for the main (executable) image; SHR1.FOR and SHR2.FOR are the source files for the shareable image to be debugged.
You compile the source files for each image as described in Section 5.1.
$ FORTRAN/NOOPT/DEBUG MAIN,SUB1 $ FORTRAN/NOOPT/DEBUG SHR1,SHR2 |
On VAX processors, use the LINK command with the UNIVERSAL linker option to create the shareable image and specify any universal symbols. For example:
$ LINK/SHAREABLE/DEBUG SHR1,SHR2,SYS$INPUT:/OPTIONS UNIVERSAL=SHR_ROUT [Ctrl/Z] |
On Alpha processors, use the LINK command with the SYMBOL_VECTOR option to create the shareable image and specify any universal symbols. For example:
$ LINK/SHAREABLE/DEBUG SHR1,SHR2,SYS$INPUT:/OPTIONS SYMBOL_VECTOR=(SHR_ROUT=PROCEDURE) [Ctrl/Z] |
In the previous examples:
You have now built the shareable image SHR1.EXE in your current default directory. Because SHR1.EXE is a shareable image, you do not execute it explicitly. Instead you link SHR1.EXE against the main (executable) image:
$ LINK/DEBUG MAIN,SUB1,SYS$INPUT:/OPTIONS SHR1.EXE/SHAREABLE [Ctrl/Z] $ |
In the previous example:
When you execute the resulting main image, MAIN.EXE, any shareable images linked against it are loaded at run time. However, by default, the image activator looks for shareable images in the system default shareable image library directory, SYS$SHARE. Therefore, you must define the logical name SHR1 to point to SHR1.EXE in your current default directory. Be sure to specify the device and directory:
$ DEFINE SHR1 SYS$DISK:[]SHR1.EXE |
You can now bring both MAIN and SHR1 under debugger control by specifying MAIN with the debugger RUN command (after starting the debugger):
$ DEBUG/KEEP Debugger Banner and Version Number DBG> RUN MAIN |
All the concepts covered in Section 5.1, Section 5.2, and Section 5.3 apply to the modules of a single image, namely the main (executable) image. This section provides additional information that is specific to debugging shareable images.
When you link shareable images for debugging as explained in Section 5.4.1, the linker builds a DST and a GST for each image. The GST for a shareable image contains only universal symbols. To conserve memory, the debugger builds an RST for an image only when that image is set, either dynamically by the debugger or when you use a SET IMAGE command.
The SHOW IMAGE command identifies all shareable images that are linked with your program, shows which images are set, and identifies the current image (see Section 5.4.2.2 for a definition of the current image). Only the main image is set initially when you bring the program under debugger control.
The following sections explain how the debugger sets images dynamically during program execution and how you can access symbols in arbitrary images independently of execution.
See Section 3.4.3.4 for information about setting watchpoints in
installed writable shareable images.
5.4.2.1 Accessing Symbols in the PC Scope (Dynamic Mode)
By default, dynamic mode is enabled. Therefore, whenever the debugger interrupts execution, the debugger sets the image and module where execution is paused, if they are not already set.
Dynamic mode gives you the following access to symbols automatically:
By setting other modules in that image with the SET MODULE command, you can reference any symbol defined in the image.
After an image is set, it remains set until you cancel it with the
CANCEL IMAGE command. If the debugger slows down as more images and
modules are set, use the CANCEL IMAGE command. You can also enter the
SET MODE NODYNAMIC command to disable dynamic mode.
5.4.2.2 Accessing Symbols in Arbitrary Images
The last image that you or the debugger sets is the current image. The current image is the debugging context for symbol lookup. Therefore, when using the following commands, you can reference only the symbols that are defined in the current image:
DEFINE/ADDRESS
DEFINE/VALUE
DEPOSIT
EVALUATE
EXAMINE
TYPE
(SET,CANCEL) BREAK
(SET,SHOW,CANCEL) MODULE
(SET,CANCEL) TRACE
(SET,CANCEL) WATCH
SHOW SYMBOL
Note that the SHOW BREAK, SHOW TRACE, and SHOW WATCH commands identify any breakpoints, tracepoints, or watchpoints that have been set in all images.
To reference a symbol in another image, use the SET IMAGE command to make the specified image the current image, then use the SET MODULE command to set the module where that symbol is defined (the SET IMAGE command does not set any modules). The following sample program shows these concepts.
The sample program consists of a main image PROG1 and a shareable image SHR1. Assume that you have just brought the program under debugger control and that execution is paused within the main program unit in image PROG1. Assume that you want to set a breakpoint on routine ROUT2, which is defined in some module in image SHR1.
If you try to set a breakpoint on ROUT2, the debugger looks for ROUT2 in the current image, PROG1:
DBG> SET BREAK ROUT2 %DEBUG-E-NOSYMBOL, symbol 'ROUT2' is not in symbol table DBG> |
The SHOW IMAGE command shows that image SHR1 needs to be set:
DBG> SHOW IMAGE image name set base address end address *PROG1 yes 00000200 000009FF SHR1 no 00001000 00001FFF total images: 2 bytes allocated: 32856 DBG> SET IMAGE SHR1 DBG> SHOW IMAGE image name set base address end address PROG1 yes 00000200 000009FF *SHR1 yes 00001000 00001FFF total images: 2 bytes allocated: 41948 DBG> |
SHR1 is now set and is the current image. However, because the SET IMAGE command does not set any modules, you must set the module where ROUT2 is defined before you can set the breakpoint:
DBG> SET BREAK ROUT2 %DEBUG-E-NOSYMBOL, symbol 'ROUT2' is not in symbol table DBG> SET MODULE/ALL DBG> SET BREAK ROUT2 DBG> GO break at routine ROUT2 10: SUBROUTINE ROUT2(A,B) DBG> |
Now that you have set image SHR1 and all its modules and have reached the breakpoint at ROUT2, you can debug using the normal method (for example, step through the routine, examine variables, and so on).
After you have set an image and set modules within that image, the image and modules remain set even if you establish a new current image. However, you have access to symbols only in the current image at any one time.
Previous | Next | Contents | Index |