| Previous | Contents | Index |
In Ada, as in other languages, the initial entry point is the procedure main, but unlike other languages, main in Ada is not the top-level application procedure. Instead, the elaboration code, which contains initialization routines for Ada-specific constructs such as packages, is called from a fabricated main routine before the top-level application is called.
If you wish to debug elaboration code, you can set a breakpoint on
main, step to elaboration code
initialization routine calls, and step into these routines. To ignore
elaboration code, you can set a breakpoint in the Ada subprogram.
7.9 Accessing Unconstrained Array Types
Accesses to unconstrained arrays are implemented as pointers to structures known as descriptors or dope vectors. For example:
procedure Dbg_30 is
type A1 is access String;
X1 : A1 := new String'("123");
begin
null;
end;
|
When you enter the print command, the debugger displays the pointer address (the address of the first (lo1) component) and the values of the first and last components. For example:
(ladebug) p *X1
struct {
pointer = 0x14000c620;
lo1 = 1;
hi1 = 3;
}
|
To examine individual components, use the dereferencing operator (->) as follows:
(ladebug) p X1->pointer[0]; p X1->pointer[2]
struct {
value = '1';
}
struct {
value = '3';
}
|
The full type often appears in a different compilation unit than the access type, which makes values of these types difficult to examine. Except in cases where the full type is an array type, you can examine values by carefully setting scopes and explicit type conversion. For example:
package Tmp_Pkg is
type A_T is private;
X : A_T;
private
type T;
type A_T is access T;
end Tmp_Pkg;
package body Tmp_Pkg is
type T is record C1, C2 : Integer; end record;
begin
X := new T'(71,72);
end Tmp_Pkg;
with Tmp_Pkg;
procedure Tmp is
begin
null;
--
-- (ladebug) whereis X
-- "tmp_pkg_.ada"`X
--
-- (ladebug) p "/c/project/aosf_ft2/tmp_pkg_.ada"`X
-- 0x14000c600
--
-- (ladebug) file tmp_pkg.ada
--
-- (ladebug) p * ( (T*) (0x14000c600) )
-- struct {
-- C1 = 71;
-- C2 = 72;
-- }
--
end;
|
Ladebug and the Tru64 UNIX operating system support the DEC Ada
language with certain limitations, which are described in the following
sections.
7.11.1 Limitations for Expressions in Ladebug Commands
Expressions in Ladebug commands use C source language syntax for operators and expressions. Data is printed as the equivalent C data type.
Table 7-1 shows Ada expressions and the debugger equivalents.
| Ada Expression | Debugger Equivalent |
|---|---|
| Name | See Section 7.4. |
| Binary operations and unary operations | Only integer, floating, and Boolean expressions are easily expressed. |
| a+b,-,* | a+b,-,* |
| a/b | a/b |
| a = b /= < <= > >= | a :=,= b != < <= > >= |
| a and b | a&&b |
| a or b | a||b |
| a rem b | a%b |
| not (a=b) | !(a:=,=b) |
| --a | --a |
| Qualified expressions | None. There is no easy way of evaluating subtype bounds. |
| Type conversions |
Only simple numeric conversions are supported, and the bounds checking
cannot be done. Furthermore, float -> integer truncates rather than
rounds.
integer -> float (ladebug) print (float) (2147483647) |
| Attributes |
None, but if E is an enumeration type with default representations for
the values then
E'PRED(X) is the same as x-1. E'SUCC(X) is the same as x+1 |
| p.all | *p (pointer reference) |
| p.m | p -> m (member of an "access record" type) |
This section lists the limitation notes by data type. For more information on these types, with examples, see the Developing Ada Programs on Tru64 UNIX Systems manual. Also see the the DEC Ada release notes for detailed information on debugging.
All Types
The debugger, unlike the Ada language, allows out-of-bounds assignments to be performed.
Integer Types
If integer types of different sizes are mixed (for example, byte-integer and word-integer), the one with the smaller size is converted to the larger size.
Floating-Point Types
If integer and floating-point types are mixed in an expression, the debugger converts the integer type to a floating-point type.
The debugger displays floating-point values that are exact integers in integer literal format.
Fixed-Point Types
The debugger displays fixed-point values as real-type literals or as structures. The structure contains values for the sign and the mantissa. To display the structure's value, multiply the sign and mantissa values. For example:
procedure Tmp3 is
type F is delta 0.1 range -3.0 .. 9.0;
X : F := 1.0;
begin
X := X+1.0;
end;
(ladebug) s
stopped at [Tmp3:5 0x1200023dc]
5 X := X+1.0;
(ladebug) print X
struct {
fixed_point, small = 0.625E-1 * mantissa = 32;
}
|
Enumeration Types
The debugger displays enumeration values as the actual enumeral or its position.
Enumeration values must be manually converted to 'pos values before you can use them as array indices.
Array Types
The debugger displays string array values in horizontal ASCII format, enclosed in quotation ("x") marks. A single component (character) is displayed within single quotation ('x') marks.
The debugger allows you to assign a component value to a single component; you cannot assign using an entire array or array aggregate.
Arrays whose components are neither a single bit nor a multiple of bytes are described to the debugger as structures; a print command displays only the first component of such arrays.
Records
The debugger cannot display record components whose offsets from the start of the record are not known at compile time.
For variant records, however, the debugger can display the entire record object that has been declared with the default variant value. The debugger allows you to print or assign a value to a component of a record variant that is not active.
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, the debugger displays the memory location of the object
it designates. You can examine the memory location value.
7.11.3 Limitations for Tasking Programs
When you debug Ada tasking programs, you use the debugger and the DEC
Ada ada_debug routine.
7.12 Debugging Programs That Generate an Exception
Ada exceptions can be raised in the following cases:
When an exception occurs, you need to determine the following:
The following sections give more detail.
Determining Where the Exception Is Being Raised
There are two ways to determine where an exception is being raised:
(ladebug) where >0 0x120007f0c in Dbg_24a$ELAB(=0x14000e400, =0x14000e3c8) dbg_24a.ada:13 |
(ladebug) 0x120007f0c-4 /2i [Dbg_24a$ELAB:13, 0x120007f08] ornot zero, zero, t1 *[Dbg_24a$ELAB:13, 0x120007f0c] srl t1, 0x21, t1 |
Determining How the Exception Is Being Raised
Having determined where the exception is occurring, examine your program code to see whether an explicit raise statement has caused the exception. If a raise statement does not appear, then the exception is the result of an Ada language check.
Determining Why the Exception Is Being Raised
If the exception is raised by an explicit raise statement, examine your code to determine why the raise statement was executed.
If the exception is raised by a language check, see Developing Ada
Programs on Tru64 UNIX Systems for tips on pinpointing the
error.
7.13 Debugging Optimized Programs
The DEC Ada compiler performs code optimizations by default, unless you specify the -g flag. Debugging optimized code is recommended only if unoptimized code is unavailable. It is extremely difficult to understand your program by examining the workings of its optimized form.
If you must debug optimized code, then note the following changes that optimization may make in your source code:
You may wish to make use of the following aids when debugging optimized code:
To help you debug DEC COBOL programs on the Tru64 UNIX operating system, Ladebug supports:
(ladebug) print itema + itemb |
The following features are also supported for DEC COBOL debugging:
Some of the features are further described in this chapter. This chapter also:
To use the Ladebug debugger on a COBOL program, invoke the COBOL compiler with the appropriate debugging flag: -g, -g2, or -g3. For example:
% cobol -g -o sample sample.cob |
The -g flag on the compiler command instructs the compiler to write the program's debugger symbol table into the executable image. This flag also turns off optimization; optimization (which is the default for nondebugger compilations) could cause a confusing debugging session.
For DIGITAL UNIX Vesion 3.2 systems, Table 8-1 summarizes the information provided by the -gn flags and their relationship to the -On flags, which control optimization. Refer to your language compiler documentation for information about compiler flag defaults for DIGITAL UNIX Version 5.0.
| Flag | Traceback Information |
Debugging Symbol Table Information |
Effect on -On Flags |
|---|---|---|---|
| -g0 | No | No | Default is -O4 (full optimization). |
| -g1 (default) | Yes | No | Default is -O4 (full optimization). |
| -g2 or -g | Yes | Yes. For unoptimized code only. | Changes default to -O0 (no optimization). |
| -g3 | Yes | Yes. Use with optimized code. Inaccuracies may result. | Default is -O4 (full optimization). |
If you specify -g, -g2, or -g3, the compiler provides symbol table information for symbolic debugging. The symbol table allows the debugger to translate virtual addresses into source program routine names and compiler-generated line numbers.
Later, to remove this symbol table information, you can compile and link it again (without the -g flag) to create a new executable program or use the strip command (see strip(1)) on the existing executable program.
The -g2 or -g flag provides symbol table information for symbolic debugging unoptimized code. If you use the -g2 or -g flag and do not specify an -On flag, the default optimization level changes to -O0 (in all other cases, the default optimization level is -O4) . If you use this flag and specify an -On flag other than -O0, a warning message is displayed. For example:
% cobol -g -O sample sample.cob cobol: Warning: file not optimized; use -g3 for debug with optimize % |
The -g3 flag is for symbolic debugging with optimized code.
Typical uses of the debugging flags at the various stages of program development are as follows:
Ladebug supports the case insensitivity of COBOL identifiers and the hyphen-underscore exchanges made by the DEC COBOL compiler.
In case-insensitive languages (such as COBOL, Fortran, and Ada), you can enter identifiers in either uppercase or lowercase, or a combination of both. For example, the following are all legal and equivalent identifiers:
Identifier IDENTIFIER identifier IdEnTiFiEr |
Ladebug and the DEC COBOL compiler treat all forms of identifers as references to the same object.
The DEC COBOL compiler performs transformations on identifiers with regard to both case and occurrences of hyphens and underscores. These transformed identifiers are visible in the listing file and in the symbol table of an image compiled with the -g flag. The rules for transformations are as follows:
Ladebug transforms all identifiers according to rule 2. When such a transformation causes a namespace conflict, an identifier is considered overloaded. When overloading occurs, it is necessary that you qualify an identifier to make it unique, as shown in Example 8-1, which demonstrates the application of the rules for transformation. Example 8-2 shows how Ladebug handles the COBOL identifiers.
| Example 8-1 Sample COBOL Program |
|---|
example.cob: * Ladebug Version 4.0 * * Demonstrates usage of COBOL expressions with Ladebug * * There are three procedures in this file, namely cobol_example, * overloaded_name and b-2. * * (Rule #1) * In cobol_example, note the symbols B-2 and C_3: these two are given as * external and appear in the symbol table as B_2 and C_3 respectively. * C-3 and C_3 are equivalent as are D-3 and D_3 * * (Rule #2) * In the procedure COBOL_EXAMPLE is the symbol overloaded-name, which appears * in the symbol table as OVERLOADED-NAME * * (Rule #3) * The procedure OverLoaded-NAME appears in the symbol table as * overloaded_name. * The procedure b-2 appears in the symbol table as b_2 * * Note that there are three names referred to as B-2: * * "example.cob"`cobol_example`B_2 -- PIC X external * "example.cob"`overloaded_name`B-2 -- PIX 99 * "example.cob"`b_2 -- program id * IDENTIFICATION DIVISION. PROGRAM-ID. COBOL_EXAMPLE. (1) DATA DIVISION. WORKING-STORAGE SECTION. 01 A_1 PIC X VALUE IS "1". 01 B-2 PIC X external. (2) 01 C_3 PIC X external. 01 D-4 PIC X VALUE IS "4". 01 overloaded-name pic 99. (3) PROCEDURE DIVISION. P0-lab. DISPLAY "*** Ladebug COBOL Example ***". MOVE "2" TO B_2. MOVE "3" TO C-3. DISPLAY "A_1 = " A_1. DISPLAY "B-2 = " B-2. DISPLAY "C_3 = " C_3. (4) DISPLAY "C-3 = " C-3. P0_lab. DISPLAY "D-4 = " D-4. (5) DISPLAY "D_4 = " D_4. CALL "Overloaded-Name". (6) CALL "B-2". DISPLAY "***END Ladebug COBOL Example***". STOP RUN. end program cobol-example. identification division. program-id. OverLoaded-NAME. (6) data division. working-storage section. 01 b_2 pic 99 value is 12. (7) procedure division. beg1. display "*** Overloaded-Name ***". display "b_2 = " b-2. (7) display "*** end of Overloaded-Name ***". end program overloaded-name. identification division. program-id. b-2. (8) data division. working-storage section. procedure division. beg1. display "*** b_2 ***". display "*** end of b_2 ***". end program b-2. |
| Previous | Next | Contents | Index |