Document revision date: 30 March 2001

## OpenVMS Debugger Manual

Previous | Contents | Index

### C.2.4 Compiling and Linking

The Ada predefined units in the ADA$PREDEFINED program library on your system have been compiled with the /NODEBUG qualifier. Before using the debugger to refer to names declared in the predefined units, you must first copy the predefined unit source files using the ACS EXTRACT SOURCE command. Then, you must compile the copies into the appropriate library with the /DEBUG qualifier, and relink the program with the /DEBUG qualifier.

If you use the /NODEBUG qualifier with one of the Ada compilation commands, only global symbol records are included in the modules for debugging. Global symbols in this case are names that the program exports to modules in other languages by means of the Ada export pragmas:

> EXPORT_PROCEDURE
> EXPORT_VALUED_PROCEDURE
> EXPORT_FUNCTION
> EXPORT_OBJECT
> EXPORT_EXCEPTION
> PSECT_OBJECT

The /DEBUG qualifier on the ACS LINK command causes the linker to include all debugging information in the closure of the specified unit in the executable image.

### C.2.5 Source Display

Source code may not be available for display for the following reasons that are specific to Ada programs:

- Execution is paused within Ada initialization or elaboration code, for which no source code is available.
- The copied source file is not in the program library where the unit was originally compiled.
- The external source file is not where it was when the unit was originally compiled.
- The source file has been modified since the executable image was generated, and the original copied source file or external source file no longer exists.

The following paragraphs explain how to control the display of source code with Ada programs.

If the compiler command's /COPY_SOURCE qualifier (the default) was in effect when you compiled your program, the debugger obtains the displayed Ada source code from the copied source files located in the program library where the program was originally compiled. If you compiled your program with the /NOCOPY_SOURCE qualifier, the debugger obtains the displayed Ada source code from the external source files associated with your program's compilation units.

The file specifications of the copied or external source files are embedded in the associated object files. For example, if you have used the ACS COPY UNIT command to copy units, or the DCL command COPY or BACKUP to copy an entire library, the debugger still searches the original program library for copied source files. If, after copying, the original units have been modified or the original library has been deleted, the debugger may not find the original copied source files. Similarly, if you have moved the external source files to another disk or directory, the debugger may not find them.

In such cases, use the SET SOURCE command to locate the correct files for source display. You can specify a search list of one or more program library or source code directories. For example (ADA$LIB is the logical name that the program library manager equates to the current program library):

    DBG> SET SOURCE ADA$LIB,DISK:[SMITH.SHARE.ADALIB]

The SET SOURCE command does not affect the search list for the external source files that the debugger fetches when you use the debugger EDIT command. To tell the EDIT command where to look for your source files, use the SET SOURCE/EDIT command.

### C.2.6 EDIT Command

With Ada programs, by default the debugger EDIT command fetches the external source file that was compiled to produce the compilation unit in which execution is currently paused. You do not edit the copied source file, in the program library, that the debugger uses for source display.

The file specifications of the source files you edit are embedded in the associated object files during compilation (unless you specify /NODEBUG). If some source files have been relocated after compilation, the debugger may not find them.

In such cases, you can use the debugger SET SOURCE/EDIT command to specify a search list of one or more directories where the debugger should look for source files. For example:

    DBG> SET SOURCE/EDIT [],USER:[JONES.PROJ.SOURCES]

The SET SOURCE/EDIT command does not affect the search list for copied source files that the debugger uses for source display.

The SHOW SOURCE/EDIT command displays the source-file search list currently being used for the EDIT command. The CANCEL SOURCE/EDIT command cancels the source-file search list currently being used for the EDIT command and restores the default search mode.

### C.2.7 GO and STEP Commands

Note the following points about using the GO and STEP commands with Ada programs:

- When starting a debugging session, use the GO command rather than the STEP command to avoid stepping through compiler-generated initialization code.
  - Use the GO command to go directly to the preset breakpoint at the start of the main program, past the initialization and package elaboration code.
  - Use the GO command and breakpoints to suspend execution at the start of the elaboration of library packages, before execution reaches the main program.
  For information on how to monitor the package elaboration phase, type Help Debugging_Ada_Library_Packages.
- If a line contains more than one statement, a STEP command executes all the statements on that line as part of a single step.
- Ada task entry calls are not the same as subprogram calls because task entry calls are queued and may not execute right away. If you use the STEP command to move execution into a task entry call, the results might not be what you expect.

### C.2.8 Debugging Ada Library Packages

When an Ada main program (or a non-Ada main program that calls Ada code) is executed, initialization code is executed for the Ada run-time library and elaboration code for all library units that the program depends on. The elaboration code causes the library units to be elaborated in appropriate order before the main program is executed. Library specifications, bodies, and some of their subunits are also elaborated by this process.

The elaboration of library packages accomplishes the following operations:

- Causes package declarations to take effect
- Initializes any variables whose declaration includes initialization code
- Executes any sequence of statements that appear between the begin and end statements of package bodies

When you bring an Ada program under debugger control, execution is paused initially before the initialization code is executed and before the elaboration of library units. For example:

    DBG> RUN FORMS
    Language: ADA, Module: FORMS
    Type GO to reach main program
    DBG>

At that point, before typing GO to get to the start of the main program, you can step through and examine parts of the library packages by setting breakpoints at the package specifications or bodies you are interested in. You then use the GO command to get to the start of each package. To set a breakpoint on a package body, specify the package unit name with the SET BREAK command. To set a breakpoint on a package specification, specify the package unit name followed by a trailing underscore character (_).

Even if you have set a breakpoint on a package body, the break will not occur if the debugger module for that body is not set. If the module is not set, the break will occur at the package specification. This effect occurs because the debugger automatically sets modules for the specifications of packages named in with clauses; it does not automatically set modules for the associated package bodies (see Section C.2.14).

Also, to set a breakpoint on a subprogram declared in a package specification, you must set the module for the package body.

Note that the compiler generates unique names for subprograms declared in library packages that are or could be overloaded names. The debugger uses these unique names in its output, and requires them in commands where the names would otherwise be ambiguous. For more information on resolving overloaded names and symbols, see Section C.2.15.

### C.2.9 Predefined Breakpoints

When you start the debugger with an Ada program (or a non-Ada program that calls Ada code), two breakpoints that are associated with Ada tasking exception events are automatically established. These breakpoints are established automatically during debugger initialization when the Ada run-time library is present.

When you enter a SHOW BREAK command under these conditions, the following breakpoints are displayed:

    DBG> SHOW BREAK
    Predefined breakpoint on ADA event "EXCEPTION_TERMINATED"
        for any value
    Predefined breakpoint on ADA event "DEPENDENTS_EXCEPTION"
        for any value
    DBG>

### C.2.10 Monitoring Exceptions

The debugger recognizes three kinds of exceptions in Ada programs:

- A user-defined exception---an exception declared with the Ada reserved word exception in an Ada compilation unit
- An Ada predefined exception, such as PROGRAM_ERROR or CONSTRAINT_ERROR
- Any other (non-Ada) exception or condition

The following subtopics explain how to monitor such exceptions.

#### C.2.10.1 Monitoring Any Exception

The SET BREAK/EXCEPTION command enables you to set a breakpoint on any exception or condition. This includes certain conditions that are signaled internally within the Ada run-time library. These conditions are an implementation mechanism; they do not represent program failures, and they cannot be handled by Ada exception handlers. If these conditions appear while you are debugging your program, you may want to consider specifying the kind of exceptions when setting breakpoints.

The following example shows a tracepoint occurring for an Ada CONSTRAINT_ERROR exception as the result of a SET TRACE/EXCEPTION command:

    DBG> SET TRACE/EXCEPTION
    DBG> GO
         ...
    %ADA-F-CONSTRAINT_ERRO, CONSTRAINT_ERROR
    -ADA-I-EXCRAIPRI, Exception raised prior to PC = 00000A7C
    trace on exception preceding
        ADA$RAISE\ADA$RAISE_CONDITION.%LINE 333+12
         ...

In the next example, the SHOW CALLS command displays a traceback of the calls leading to the subprogram where the exception occurred or to which the exception was raised:

    DBG> SET BREAK/EXCEPTION DO (SHOW CALLS)
    DBG> GO
          ...
    %SYSTEM-F-INTDIV, arithmetic trap, integer divide
         by zero at PC=000008AF,
    PSL=03C000A2 break on exception preceding
         SYSTEM_OPS.DIVIDE.%LINE 17+6
         17:      return X/Y;
     module name     routine name       line    rel PC    abs PC
    *SYSTEM_OPS      DIVIDE               17   00000015  000008AF
    *PROCESSOR       PROCESSOR            19   000000AE  00000BAD
    *ADA$ELAB_PROCESSOR
                     ADA$ELAB_PROCESSOR        00000009  00000809
                     LIB$INITIALIZE            00000054  00000C36
     SHARE$ADARTL                              00000000  000398BE
    *ADA$ELAB_PROCESSOR
                     ADA$ELAB_PROCESSOR        0000001B  0000081B
                     LIB$INITIALIZE            0000002F  00000C21

In this example, the condition SS$_INTDIV is raised at line 17 of the subprogram DIVIDE in the package SYSTEM_OPS. The example shows an important effect: some conditions (such as SS$_INTDIV) are treated as being equivalent to some Ada predefined exceptions.

The matching of a condition and an Ada predefined exception is performed by the condition handler provided by Ada for any frame that includes an exception part. Therefore, when an exception breakpoint or tracepoint is triggered by a condition that has an equivalent Ada exception name, the message displays only the system condition code name, and not the name of the corresponding Ada exception.

#### C.2.10.2 Monitoring Specific Exceptions

Whenever an exception is raised, the debugger sets the following built-in symbols. You can use them to qualify exception breakpoints or tracepoints so that they trigger only on certain exceptions.

%EXC_FACILITY | A string that names the facility that issued the exception. The facility name for Ada predefined exceptions and user-defined exceptions is ADA.
%EXC_NAME | An uppercase string that names the exception. If the exception raised is an Ada predefined exception, its name is truncated if it exceeds 15 characters. For example, CONSTRAINT_ERROR is truncated to CONSTRAINT_ERRO. If the exception is a user-defined exception, %EXC_NAME contains the string "EXCEPTION", and the name of the user-defined exception is contained in %ADAEXC_NAME.
%ADAEXC_NAME | If the exception raised is user-defined, %ADAEXC_NAME contains a string that names the exception, and %EXC_NAME contains the string "EXCEPTION". If the exception is not user-defined, %ADAEXC_NAME contains a null string, and the name of the exception is contained in %EXC_NAME.
%EXC_NUM | The number of the exception.
%EXC_SEVERITY | A string that gives the exception severity level (F, E, W, I, S, or ?).

#### C.2.10.3 Monitoring Handled Exceptions and Exception Handlers

The SET BREAK/EVENT and SET TRACE/EVENT commands let you set breakpoints and tracepoints on exceptions that are about to be handled by Ada exception handlers. These commands let you observe the execution of each Ada exception handler that gains control.

You can specify two event names with these commands:

HANDLED | Triggers when an exception is about to be handled in an Ada exception handler (includes `HANDLED_OTHERS` events).
HANDLED_OTHERS | Triggers only when an exception is about to be handled in an Ada exception handler choice `others` .

For example, the following command sets a breakpoint that triggers whenever an exception is about to be handled by an Ada exception handler:

    DBG> SET BREAK/EVENT=HANDLED

When the breakpoint triggers, the debugger identifies the exception that is about to be handled and the exception handler that is about to be executed. You can then use that information to set a breakpoint on a particular handler, or you can enter the GO command, and see which Ada handler next attempts to handle the exception. For example:

    DBG> GO
         ...
    break on Ada event HANDLED
      task %TASK 1 is about to handle an exception
      The Ada exception handler is at: PROCESSOR.%LINE 21
        %ADA-F-CONSTRAINT_ERRO, CONSTRAINT_ERROR
        -ADA-I-EXCRAIPRI, Exception raised prior to PC = 00000A7C
    DBG> SET BREAK PROCESSOR.%LINE 21; GO

### C.2.11 Examining and Manipulating Data

When examining and manipulating data, note the following considerations:

- Before you can examine or deposit into a nonstatic variable (any variable not declared in a library package), its defining subprogram, task, and so on, must be active on the call stack.
- Before you can examine, deposit, or evaluate an Ada subprogram formal parameter or an Ada variable, the parameter or variable must be elaborated. In other words, you should step or otherwise move execution past the parameter or variable's declaration. The value contained in any variable or formal parameter whose declaration has not been elaborated might be invalid.

In most cases, the debugger enables you to specify variables and expressions in debugger commands exactly as you would specify them in the source code of the program, including use of qualified expressions. The following subtopics discuss some additional points about debugger support for records and access types.

#### C.2.11.1 Records

Note the following points about debugger support for records:

- With certain Ada record variables, the debugger fails to show the record components correctly (possibly with a NOACCESSR error message) when the type declaration is in a different scope than the record (symbol) declaration.
- With variant records, the debugger lets you examine or assign a value to a component of a variant part that is not active. But because this is an illegal action in Ada, the debugger also issues an informational message. For example, assume that record REC1 has a variant field named STATUS and that the value of STATUS is such that REC1.COMP3 is inactive:

      DBG> EXAMINE REC1.COMP3
      %DEBUG-I-BADDISCVAL, incorrect value of 1 in discriminant
          field STATUS
      MAIN.REC1.COMP3:    438

#### C.2.11.2 Access Types

Note the following points about debugger support for access types:

- The debugger does not support allocators, so you cannot create new access objects with the debugger.
- When you specify the name of an access object with the EXAMINE command, the debugger displays the memory location of the object it designates.
- To examine the value of a designated object, you must use selected component notation, specifying .ALL. For example, to examine the value of a record access object designated by A:

      DBG> EXAMINE A.ALL
      EXAMPLE.A.ALL
          NAME(1..10):        "John Doe  "
          AGE :       6
          NEXT:       1462808

- To examine one component of a designated object, you can omit .ALL from the selected component syntax. For example:

      DBG> EXAMINE A.NAME
      EXAMPLE.A.ALL.NAME(1..10):     "John Doe  "

The following example shows the debugger support for incomplete types. Consider the following declarations:

    package P is
       type T is private;
    private
       type T_TYPE;
       type T is access T_TYPE;
    end P;

    package body P is
       type T_TYPE is
          record
            A: NATURAL := 5;
            B: NATURAL := 4;
          end record;

       T_REC: T_TYPE;
       T_PTR: T := new T_TYPE'(T_REC);
    end P;

    with P; use P;
    procedure INCOMPLETE is
       VAR: T;
    begin
       ...
    end INCOMPLETE;

The debugger does not have complete information about the type T, so you cannot manipulate the variable VAR. However, the debugger does have information about objects declared in the package body P. Thus, you can manipulate the variables T_PTR and T_REC.

### C.2.12 Module Names and Path Names

The names of Ada debugger modules are the same as the names of the corresponding compilation units, with the following provision. To eliminate ambiguity, an underscore character (_) is appended to a specification name to distinguish it from its body name. For example, TEST (body), TEST_ (specification). To determine the exact names of the modules in your program, use the SHOW MODULE command.

In most cases when you specify a path name, the debugger can distinguish body names and specification names from the context. Therefore, use this naming convention only if needed to resolve an ambiguity.

When the debugger language is set to Ada, the debugger generally constructs pathnames that follow the Ada rules, using selected component notation to separate path name elements (with other languages, a backslash is used to separate elements). For example:

    TEST_.A1        ! A1 is declared in the package
                     ! specification of unit TEST
    TEST.B1         ! B1 is declared in the package
                     ! body of unit TEST

The maximum length that you can specify for a subunit path name (expanded name) is 247 characters.

When a use clause makes a symbol declared in a package directly visible outside the package, you do not need to specify an expanded name (package-name.symbol) to refer to the symbol, either in the program itself or in debugger commands.

The SHOW SYMBOL/USE_CLAUSE command identifies any package (library or otherwise) that a specified block, subprogram, or package mentions in a use clause. If the entity specified is a package (library or otherwise), the command also identifies any block, subprogram, package, and so on, that names the specified module in a use clause. For example:

    DBG> SHOW SYMBOL/USE_CLAUSE B_
    package spec B_
        used by:  F
        uses:     A_

If a label has been assigned to a loop statement or declare block in the source code, the debugger displays the label; otherwise, the debugger displays LOOP$n for a loop statement or BLOCK$n for a declare block, where n is the line number at which the statement or block begins.

### C.2.13 Symbol Lookup Conventions

For Ada programs, when you do not specify a path name (including an Ada expanded name), the debugger searches the run-time symbol table as follows.

1. The debugger looks for the symbol within the block or routine surrounding the current PC value (where execution is currently paused).
2. If the symbol is not found, the debugger then searches any package that is mentioned in a use clause. The debugger does not distinguish between a library package and a package whose declaration is in the same module as the current scope region. If the same symbol is declared in two or more packages that are visible, the symbol is not unique (according to Ada rules), and the debugger issues a message similar to the following:

       %DEBUG-E-NOUNIQUE, symbol 'X' is not unique

3. If the symbol is still not found, the debugger searches the call stack and other scopes, as for other languages.

### C.2.14 Setting Modules

When you or the debugger sets an Ada module, by default the debugger also sets any "related" module (that is, any module whose symbols should be visible within the module being set). Such modules are related to the one being set through either a with-clause or a subunit relationship.

Related module setting takes place as follows. If M1 is the module that is being set, then the following modules are considered related and are also set:

- If M1 is a library body, the debugger also sets the associated library specification, if any.
- If M1 is a subunit, the debugger also sets its parent unit and, therefore, any parent of the parent.
- If M1 mentions a library package P1 in a with clause, the debugger also sets P1's specification. Neither the body of P1 nor any possible subunits of P1 are set, because symbols declared within them should not be visible outside.
  If P1's specification mentions a package P2 in a with clause, the debugger also sets P2's specification. Likewise, if P2's specification mentions a package P3 in a with clause, the debugger also sets P3's specification, and so on. The specifications of all such library packages are set so that you can access data components (for example, record components) that may have been declared in other packages.
- If M1 mentions a library subprogram in a with clause, the debugger does not set the subprogram. Only the subprogram name needs to be visible in M1 (no declaration within a library subprogram should be visible outside the subprogram). Therefore, the debugger inserts the name of the library subprogram into the RST when M1 is set.

If debugger performance becomes a problem as more modules are set, use the SET MODE NODYNAMIC command, which disables related module setting as well as dynamic module setting. You must then set individual modules explicitly with the SET MODULE command.

By default, the SET MODULE command sets related modules simultaneously with the module specified in the command.

The SET MODULE/NORELATED command sets only the modules you specify explicitly. However, if you use SET MODULE/NORELATED, you may find that a symbol that is declared in another unit and that should be visible at the point of execution is no longer visible or that a symbol which should be hidden by a redeclaration of that same symbol is now visible.

The CANCEL MODULE/NORELATED command deletes from the RST only the modules you specify explicitly. This command, which is the default, deletes related modules in a manner consistent with the intent of Ada's scope and visibility rules. The exact effect depends on module relationships.

The distinction between related and directly related for subunits is analogous to that for library packages.

Previous | Next | Contents | Index

| privacy and legal statement |
4538PRO_066.HTML