You can use Ladebug to debug Fortran programs on the Digital UNIX operating system. The following features are supported:
It is an error to specify a trailing underscore, as Ladebug removes trailing underscores when reading a Fortran symbol table.
core
files, examining the call stack, or displaying
registers.
This chapter also discusses flags used with the Fortran compiler commands,+ Fortran data types in Ladebug, limitations on Ladebug support for Fortran, debugging a Fortran program that generates an exception, and locating unaligned data.
+ f77 is the DEC Fortran compile command, and f90 is the DEC Fortran 90 compile command. In this chapter, Fortran refers to both DEC Fortran and DEC Fortran 90.
To prepare to use the Ladebug debugger on a Fortran program, invoke
the compiler with the appropriate debugging flag: -g,
-g2, or -g3
and, for DEC Fortran 90 only, -
ladebug.
For example, for DEC Fortran 90:
% f90 -g -ladebug -o squares squares.f90
For DEC Fortran:
% f77 -g -o squares squares.for
This f77
command compiles and links the program
squares.for
without optimization but with symbol
table information needed for symbolic debugging with Ladebug.
The executable file is named squares
instead of
a.out.
The -gn
flags control the amount of
information placed in the object file for debugging.
For Digital UNIX Version 3.2
systems, Table 11-1 summarizes
the information provided by the debugger-related flags and their
relationship to the -On
flags, which control
optimization. Refer to your language compiler documentation for the
latest information on compiler flags used on Digital UNIX Version
4.0 systems.
$lang
is always "Fortran" in both cases.
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 | Default is
-O4 . |
-ladebug
(f90 only) | Yes | Describes Fortran-90 arrays in a manner that Ladebug understands. | No effect. |
Traceback information and symbol table information are both necessary for debugging. They enable the debugger to:
Typical uses of the debugging flags at the various stages of program development are as follows:
-g
(or -g2
) flag, perhaps specifying
-O0
(which is the default with the -g
or -g2
flag) to enable debugging and to create
unoptimized code.
-g0
or -g1
to minimize the object
file size+ and, as a result, the memory needed for program
execution, usually with optimized code.
If further debugging is needed, compile and link using -g
to create an unoptimized debugging version of the same
application for debugging purposes.
-g3
.
Traceback and symbol table information result in a larger object
file. When you have finished debugging your program, you can remove
traceback information with the the strip
command (see
strip(1)
). To remove symbol table information, you
can compile and link again with -g0
or -g1
to create a new executable program.
If your program generates an exception, recompile using the -
fpen
flag (see Section 11.7).
For more information on program development and run-time environments, see the DEC Fortran or DEC Fortran 90 user manual.
+ -g1 results in a larger object file than -g0 but smaller than the other gn flags
When the $lang
debugger variable is set to Fortran,
command names and program identifiers are case insensitive. For more
information about the $lang
debugger variable, see Section 11.6.
To refer to a variable named J,
use either the
uppercase letter J
or its lowercase equivalent,
j.
You can also enter Ladebug command names in uppercase or lowercase. For example, the following two commands are equivalent:
(ladebug) PRINT J
(ladebug) print j
You can display the values of variables in a Fortran common
block using Ladebug commands such as print
or
whatis.
To display the entire common block, use the common block name. For example:
(ladebug) list 1,11 1 PROGRAM EXAMPLE 2 3 INTEGER*4 INT4 4 CHARACTER*1 CHR 5 COMMON /COM_STRA/ INT4, CHR 6 7 CHR = 'L' 8 > 9 PRINT *, INT4, CHR 10 11 END (ladebug) print com_stra COMMON INT4 = 0 CHR = "L"
To display a specific variable in the common block, use only the field name. For example:
(ladebug) PRINT CHR "L"
If your program contains a common block and a member of the same name, the common block will be occluded by the member.
Variables in a Fortran 90 derived-type (TYPE statement) are
represented in Ladebug commands, such as print
or
whatis
, using Fortran 90 syntax form.
For derived-type structures, use:
For example:
(ladebug) list 3,11 3 TYPE X 4 INTEGER A(5) 5 END TYPE X 6 7 TYPE(X) Z 8 9 Z%A = 1 10 > 11 PRINT*, Z%A (ladebug) print Z%A (1) 1 (2) 1 (3) 1 (4) 1 (5) 1
Variables in a Fortran record structure (STRUCTURE statement) are represented in a fashion similar to derived-type.
For record structures, use:
For example:
(ladebug) l 3,13 3 STRUCTURE /STRA/ 4 INTEGER*4 INT4 5 CHARACTER*1 CHR 6 END STRUCTURE 7 8 RECORD /STRA/ REC 9 10 REC.CHR = 'L' 11 REC.INT4 = 6 12 > 13 PRINT *, REC.CHR, REC.INT4 (ladebug) print rec%int4 6 (ladebug) print rec.int4 6
To view all fields in the record structure, type the name of
the record structure, such as rec
(instead of
rec%int4
or rec.int4
in the previous
example).
For array variables, put subscripts within parentheses, as with Fortran source statements. For example:
(ladebug) assign arrayc(1)=1
You can print out all elements of an array using its name. For example:
(ladebug) print arrayc (1) 1 (2) 0 (3) 0
Avoid displaying all elements of a large array. Instead, display specific array elements or array sections. For example, to print array element arrayc(2):
(ladebug) print arrayc(2) (2) 0
Fortran provides an array notation known as an array section. Array sections consist of a three parts, a starting element, an ending element, and a stride. For more information on arrays, see the DEC Fortran or DEC Fortran 90 user manual.
Consider the following array declarations:
INTEGER, DIMENSION(0:99) :: arr INTEGER, DIMENSION(0:9,0:9) :: TenByTen
Assume that each array has been initialized to have the value of the index in each position, for example, TenByTen(5,5) = 55, arr(43) = 43. The following expressions will be accepted by the debugger:
(ladebug) print arr(2) 2 (ladebug) print arr(0:9:2) (0) = 0 (2) = 2 (4) = 4 (6) = 6 (8) = 8 (ladebug) print TenByTen(:,3) (0,3) = 3 (1,3) = 13 (2,3) = 23 (3,3) = 33 (4,3) = 43 (5,3) = 53 (6,3) = 63 (7,3) = 73 (8,3) = 83 (9,3) = 93
The only operations permissible on array sections are
whatis
and print
.
Ladebug supports the array section notation for both Fortran-90 and Fortran-77 programs.
Ladebug does not support assignments to whole arrays, only single array elements.
To refer to a variable defined in a module, insert a dollar sign ($), the module name, and another dollar sign ($) before the variable name. For example, with a variable named J defined in a module named modfile (statement MODULE MODFILE), enter the following command to display its value:
(ladebug) list 5,7 5 USE MODFILE 6 INTEGER*4 J 7 CHARACTER*1 CHR
DEC Fortran 90 supports two types of pointers:
The following example shows Fortran 90 pointers displayed in their
corresponding source form with a whatis
command. In
the following example, the -ladebug
switch is used to
allow display of pointers to arrays. Only the display of pointers
is currently supported; it is not currently possible to change the
location to which the pointer points:
% f90 -g -ladebug ptr.f90 % ladebug ./a.out Welcome to the Ladebug Debugger Version x.y-zz ------------------ object file name: ./a.out Reading symbolic information ...done (ladebug)stop in ptr [#1: stop in ptr ] (ladebug) list 1:13 1 program ptr 2 3 integer, target :: x(3) 4 integer, pointer :: xp(:) 5 6 x = (/ 1, 2, 3/) 7 xp => x 8 9 print *, "x = ", x 10 print *, "xp = ", xp 11 12 end (ladebug) run [1] stopped at [ptr:6 0x120001838] 6 x = (/ 1, 2, 3/) (ladebug) whatis x integer*4 x (1:3)
Since xp has not been assigned to point to anything yet, it is still a generic pointer:
(ladebug) whatis xp integer*4 (:) xp (ladebug) S stopped at [ptr:7 0x120001880] 7 xp => x (ladebug) stopped at [ptr:9 0x120001954] 9 print *, "x = ", x (ladebug) x = 1 2 3 stopped at [ptr:10 0x1200019c8] 10 print *, "xp = ", xp (ladebug) xp = 1 2 3 stopped at [ptr:12 0x120001ad8] 12 end
Now that xp points to x, it takes on the size, shape and values of x:
(ladebug) whatis xp integer*4 xp (1:3) (ladebug) print xp (1) 1 (2) 2 (3) 3 (ladebug) quit %
The following example shows DEC Fortran CRAY-style pointers
displayed in their corresponding source form with a
whatis
command:
% f90 -g -ladebug cray.f90 % ladebug ./a.out Welcome to the Ladebug Debugger Version x.y-zz ------------------ object file name: ./a.out Reading symbolic information ...done (ladebug) stop at 14 [#1: stop at "cray.f90":14 ] (ladebug) run [1] stopped at [cray:14 0x1200017e4] 14 end (ladebug) whatis p real*4 (1:10) pointer p (ladebug) print p 0x140002c00 = (1) 10 (2) 20 (3) 30 (4) 40 (5) 50 (6) 60 (7) 70 (8) 80 (9) 90 (10) 100 (ladebug) l 1:14 1 program cray 2 3 real i(10) 4 pointer (p,i) 5 6 n = 5 7 8 p = malloc(sizeof(i(1))*n) 9 10 do j = 1,10 11 i(j) = 10*j 12 end do 13 > 14 end (ladebug) quit
Ladebug supports COMPLEX, COMPLEX*8, and COMPLEX*16 variables and constants in expressions.
Consider the following Fortran program:
PROGRAM complextest COMPLEX*8 C8 /(2.0,8.0)/ COMPLEX*16 C16 /(1.23,-4.56)/ REAL*4 R4 /2.0/ REAL*8 R8 /2.0/ REAL*16 R16 /2.0/ integer*2 i2 /2/ integer*4 i4 /2/ integer*8 i8 /2/ TYPE *, "C8=", C8 TYPE *, "C16=", C16 end
Ladebug supports basic arithmetic operators, display and assignment on variables and constants of the COMPLEX type. For example:
Welcome to the Ladebug Debugger Version x.y-zz ------------------ object file name: complex Reading symbolic information ...done (ladebug) stop in complextest [#1: stop in complextest ] (ladebug) run [1] stopped at [complextest:15 0x1200017b4] 15 TYPE *, "C8=", C8 (ladebug) whatis c8 complex c8 (ladebug) whatis c16 double complex c16 (ladebug) print c8 (2, 8) (ladebug) print c16 (1.23, -4.56) (ladebug) whatis (-5,6.78E+12) double complex (ladebug) print (c8*c16)/(c16*c8) (1, 0) (ladebug) a c16=(-2.3E+10,4.5e-2) (ladebug) print c16 (-23000000512, 0.04500000178813934) (ladebug)
Ladebug and the Digital UNIX operating system support the Fortran language with certain limitations, that are described in the following sections.
Be aware of the following data-type limitations when you debug a Fortran program:
The following limitations apply only to DEC Fortran 90:
% cat noprog.f90 i = 5 end
A breakpoint at main$noprog will get set at line 2, rather than line 1.
If a subprogram uses alternate entry points (ENTRY statement within the subprogram), Ladebug handles alternate entry points as a separate subprogram, including:
stop in
command).
where
command at an alternate
entry point breakpoint location.
For example, the following is a fragment of a Fortran program and a debugging session:
program aep call foo(1,2,3,4) call bar(4,5,6) end subroutine foo(I,J,K,I1) INTEGER*4 I,J,K,L,I1 write (6,*) 'Entered via foo: ', i, j, k, I1 write (6,*) '*****************************' goto 1000 entry bar(J,K,L) write (6,*) 'Entered via bar: ', j, k, l write (6,*) '*****************************' 1000 write (6,*) 'Exiting foo & bar' return end Welcome to the Ladebug Debugger Version x.y-zz ------------------ object file name: aep Reading symbolic information ...done (ladebug) stop in foo [#1: stop in foo ] (ladebug) stop in bar [#2: stop in bar ] (ladebug) status #1 PC==0x120001868 in foo "aep.f":10 { break } #2 PC==0x1200019ac in bar "aep.f":16 { break } (ladebug) run [1] stopped at [foo:10 0x120001868] 10 write (6,*) 'Entered via foo: ', i, j, k, I1 (ladebug) where >0 0x120001868 in foo(I=1, J=2, K=3, I1=4) aep.f:10 #1 0x120001814 in aep() aep.f:3 #2 0x1200017b0 in main() for_main.c:203 (ladebug) c Entered via foo: 1 2 3 4 ***************************** Exiting foo & bar [2] stopped at [bar:16 0x1200019ac] 16 write (6,*) 'Entered via bar: ', j, k, l (ladebug) where >0 0x1200019ac in bar(J=4, K=5, L=6) aep.f:16 #1 0x12000182c in aep() aep.f:4 #2 0x1200017b0 in main() for_main.c:203 (ladebug) c Entered via bar: 4 5 6 ***************************** Exiting foo & bar Thread has finished executing (ladebug) quit
The Ladebug debugger lets you debug mixed-language programs. Program flow of control across subprograms written in different languages is transparent.
The debugger automatically identifies the language of the current subprogram or code segment on the basis of information embedded in the executable file. For example, if program execution is suspended in a subprogram in Fortran, the current language is Fortran. If the debugger stops the program in a C function, the current language becomes C. The current language determines for the debugger the valid expression syntax and the semantics used to evaluate an expression.
The debugger sets the $lang
variable to the language
of the current subprogram or code segment. By manually setting the
$lang
debugger variable, you can force the debugger
to interpret expressions used in commands by the rules and semantics
of a particular language. For example, you can check the current
setting of $lang
and change it as follows:
(ladebug) print $lang "C++" (ladebug) set $lang = "Fortran"
When the debugger reaches the end of your program, the $lang
variable is set to the language of the main program.
If your program encounters an exception at run time, to make it
easier to debug the program, recompile and relink with the following
f90
flags or f77
flags before
debugging the cause of the exception:
-fpen
flag to control the
handling of exceptions (see f77(1)
or f90(1)
).
-g
flag to generate sufficient symbol table information and debug
unoptimized code (see Section 11.2).
Use the Ladebug commands catch
and ignore
to control whether Ladebug displays and handles exceptions
(catches them), or ignores exceptions so that they are handled by
the Fortran run-time library.
To obtain the appropriate Fortran run-time error message when
debugging a program that generates an exception, you may need to
use the appropriate ignore
command before running the
program. For instance, use the following command to tell Ladebug
to ignore floating-point exceptions and pass them through to the
Fortran run-time library:
(ladebug) ignore fpe
Because the where
command works only if the debugger
is catching the signal, the ignore
command prevents
the where
command from working. You may want to use
the where
command when an exception occurs to locate
the part of the program causing the error. You need to consider this
factor when you use the ignore
command.
The Fortran compiler performs code optimizations (-O4
) by default unless you specify -g2
(or -
g
) . See the DEC Fortran or DEC Fortran 90 user manual for a
discussion of compiler optimizations.
Debugging optimized code is recommended only under special
circumstances (such as a problem that shows up in an optimized
program may disappear when you specify the -O0
flag). Before you attempt to debug optimized code, read Section 11.2.
One aid to debugging optimized code is the -show code
flag. This flag generates a listing file that shows the compiled
code produced for your program. By referring to a listing of the
generated code, you can see exactly how the compiler optimizations
affected your code. This lets you determine the debugging commands
you need in order to isolate the problem.
Another aid is a set of messages displayed by Ladebug when you try to perform a Ladebug operation on a language construct that has been optimized. For example, if the Fortran compiler can determine that an entire Fortran 90 statement is not needed for correct operation of the program (such as an unnecessary CONTINUE statement), that statement is not represented in the object code. As a result, Ladebug will use the next available line.
For more information on optimizations, see the DEC Fortran or DEC Fortran 90 user manual.