This chapter describes the methods for examining information in your program with the Ladebug debugger command interface.
The list
command displays source-code lines starting
with one of the following:
list
commands are entered
list
command
When the list
command is entered without an argument,
the number of lines listed is determined by the value of the
$listwindow
debugger environment variable. The default
value of the $listwindow
variable is 20. Entering
list
(or pressing Return) lists the next 20 lines of
code. Repeated list
commands display your program's
source code in 20-line segments.
To display a range of lines, enter a list
command with
the following syntax:
list begin_line_number, end_line_number
The begin_line_number argument specifies the number associated with the starting source-code line. The end_line_ number argument specifies the number associated with the last line of source code you want listed.
Example 8-1 uses the list
command to display the lines of a COBOL program source file numbered
43 through 50.
(ladebug) list 43,50 43 PERFORM LOOK-BACK VARYING SUB-1 FROM 20 BY -1 44 UNTIL TEMP-CHAR (SUB-1) NOT = SPACE. 45 MOVE SUB-1 TO CHARCT. 46 PERFORM MOVE-IT VARYING SUB-2 FROM 1 BY 1 UNTIL SUB-1 = 0. 47 MOVE HOLD-WORD TO TEMP-WORD. 48 MOVE-IT. 49 MOVE TEMP-CHAR (SUB-1) TO HOLD-CHAR (SUB-2). 50 SUBTRACT 1 FROM SUB-1. (ladebug)
To display a specific number of lines, beginning with a particular
line, enter the list
command with the following
syntax:
list begin_line_number:count
The count argument specifies the number of lines to list.
Example 8-2 uses the list
command to display the first 25 lines of an Ada program.
(ladebug) list 1:25 1 with TEXT_IO; use TEXT_IO; 2 with INTEGER_TEXT_IO; use INTEGER_TEXT_IO; 3 with FLOAT_TEXT_IO; use FLOAT_TEXT_IO; 4 procedure TEST is 5 6 procedure P (I : INTEGER); 7 procedure P (F : FLOAT); 8 9 procedure P (I : INTEGER) is 10 TWO : constant := 2; 11 begin 12 PUT (I * TWO); 13 NEW_LINE; 14 end; 15 16 procedure P (F : FLOAT) is 17 begin 18 PUT(F); 19 NEW_LINE; 20 end; 21 22 begin 23 P(5); 24 P(6.0); 25 end; (ladebug)
To display the source code for a particular function, enter the name
of the function as an argument to the list
command.
The syntax is as follows:
list function
The debugger prints an error message if it cannot find the source file corresponding to the current function.
If the source file is not in the current directory, you can enter
a use
command to add directories to the list of
directories the debugger will search. The syntax is as follows:
use [directory]
You can enter multiple use
commands to ensure that the
debugger finds all source files associated with your program.
The unuse
command sets the search list to any of the
following:
Include the name of a directory to remove it from the search list or an asterisk (*) to remove all directories from the search list. The syntax is as follows:
unuse [directory] unuse *
You can also specify search directories as command-line arguments
to the ladebug
command with the -I
option. (See the ladebug(1)
reference page for more
information about the options to the ladebug
command.)
As explained in Chapter 7, the stack
trace lists the active functions in the program you are debugging.
Figure 8-1 shows the elements of a
stack trace that the debugger displays when you enter a where
command.
The stack trace provides the following information for each activation level:
Stack level | The number used to refer to an activation level on the stack. The function entered most recently is on activation level 0. |
Function name | The name of the function active at this activation level of the stack. The values of any variables passed to this function are also listed. |
Function parameters | The list of parameter names and values from previous function calls. |
Memory address | The address of the next instruction to be executed in the named function. |
File name | The name of the file containing the source code for the function. |
Line number | The number of the last executed source line in the function. |
Example 8-3 uses the where
command to display the stack trace of a COBOL program.
(ladebug) where >0 0x3ff81808744 in cob_acc_display() cob_accdis.c:349 #1 0x120001fbc in testa() testa.cob:20 #2 0x3ff8181f054 in main() cob_main.c:253
The debugger recognizes the scoping rules of the symbols in the target program by maintaining a current context and accessing program symbols based on this context. The context is determined by:
And, if applicable, by:
The context is automatically set to the current point of execution when the debugger is given control (for example, when the debugger stops at a breakpoint).
The debugger extends symbol accessibility beyond that allowed by the language rules when you change the current context or qualify a symbol name with full scope information.
If you do not qualify the symbol name with full scope information, the debugger looks for the symbol in the current context (including process context or thread context, if applicable). The current context is determined by the point at which execution is paused or by the context set when you change the function, file, or class scope.
If the symbol is not found, the debugger searches the calling function, and then its caller, and so on. Within each context, the debugger uses the visibility rules of the language to locate a symbol. If the symbol is still not found, the debugger searches the global symbol table.
When the debugger encounters a breakpoint and suspends program
execution, the current function is at activation level 0. The stack
trace marks the current function scope with an angle bracket (
> ). All other levels on the stack are marked with a pound
sign (#). If you want to examine a function other than the current
function, use the func,
up,
or down
command to change the current function scope.
Changing the current function scope does not change the current point of program execution. When you continue program execution, the program begins where it left off, regardless of the current function scope.
Change the function scope to examine the value of program symbols or data structures that are not visible in the current scope.
The func
command lets you specify a new current
function scope by function name. In Example 8-4 the current function scope is changed to function
main
so that a variable in main()
can be
displayed.
(ladebug) stop at 13 [#1: stop at "sample.c":13 ] (ladebug) run [1] stopped at [factorial:13 0x120000ad4] 13 if (i<=1) (ladebug) cont 1! = 1 [1] stopped at [factorial:13 0x120000ad4] 13 if (i<=1) (ladebug) print f Symbol f not visible in current scope. Error: no value for f (ladebug) where >0 0x120000ad4 in factorial(i=2) sample.c:13 #1 0x120000a54 in main() sample.c:5 (ladebug) func main main in sample.c line No. 5: 5 f = factorial(i); (ladebug) where #0 0x120000ad4 in factorial(i=2) sample.c:13 >1 0x120000a54 in main() sample.c:5 (ladebug) print f 1 (ladebug)
The up
and down
commands let you specify
a new current function scope by moving up or down a specified number
of levels on the stack trace. If you enter the up
or down
commands without an argument, you move the
current function pointer up or down one level.
In the previous example, instead of entering func main
you can enter up 1.
Note that the final stack trace
in this example lists function main
as the current
function scope (denoted by the > character).
The current file scope is automatically set to the name of the
file containing the source code of the function you are debugging.
When the function scope changes, the current file scope is updated
automatically. Use the file
command to display and
change the current file scope. You can enter this command with no
arguments to display the current file scope.
To change the file scope, enter the file
command with
the following syntax:
file filename
Enter the name of the file exactly as it was entered on the compile command line. Use a preceding directory path if necessary.
Changing the current file scope lets you list a function in the new
file or set a breakpoint on a line in the function. After loading
the file with the file
command, you can enter the
list
command to examine it.
Example 8-5 uses the file
command to set the debugger file scope back to the main
COBOL program, and then stops at line number 20 in that file.
(ladebug) file testa.cob (ladebug) stop at 20 [#6: stop at "testa.cob":20]
When you change the current file scope, the function scope is reset.
Running or continuing your program nullifies the file
command and reloads the source code corresponding to the program you
are debugging.
The debugger automatically identifies the language of the current function or code segment based on information embedded in the executable file. For example, if program execution is suspended in a C function, the current language is C. If the program executes a C++ function, the current language becomes C++. The current language determines the valid expression syntax for the debugger.
The debugger sets the $lang
variable to the language
of the current function or code segment. If the program is not
running, $lang
is set to the language of the module
in which the main entry point resides.
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
check the current setting of $lang
and change it as
follows:
(ladebug) print $lang "C++" (ladebug) set $lang = "C"
You can access program symbols when program execution is suspended in the function that defines the symbol or in any function called by the defining function. Before you can access a symbol, you must execute the program beyond the point where the symbol is declared. If you examine an expression before the variables used in the expression are initialized, the expression value may not be valid.
Use the print
command to display the value of specific
variables or expressions in functions active on the stack. You
can also use the print
command to evaluate complex
expressions involving typecasts, pointer dereferences, multiple
variables, constants, and any legal operators allowed by the
language of the program you are debugging.
You cannot print a program symbol until you have started executing
the program using the run
or rerun
command. You can use the set
command to view the
values of debugger variables before starting execution.
The syntax for the print
command is as follows:
print expression
The debugger formats expression values according to the type defined
for them in the program. You can print an expression's type using
the whatis
command. The syntax for the whatis
command is as follows:
whatis expression
Example 8-6 uses the whatis
command to examine the contexts of the data item SUB-1
in the COBOL program TESTA.
(ladebug) whatis sub-1 unsigned short SUB-1 (ladebug) print sub-1 0 (ladebug)
Consider the following declarations in an Ada program:
type DAY is (MON,TUES,WED,THURS,FRI,SAT,SUN); MY_DAY : DAY := MON;
Example 8-7 uses the whatis
command to determine the storage representation for the
variable MY_DAY.
(ladebug) whatis MY_DAY enum DAY { MON, TUES, WED, THURS, FRI, SAT, SUN } MY_DAY; (ladebug) print MY_DAY MON
For an array, the debugger prints every cell in the array if you do not specify a specific cell.
Consider the following declarations in an Ada program:
type CAR is (BUICK,FORD,HONDA); type CAR_ARRAY is array (CAR) of INTEGER; CAR_NUM : CAR_ARRAY := (1,2,3);
Example 8-8 uses the print
command to display a nonstring array.
(ladebug) print CAR_NUM [0] = 1,[1] = 2,[2] = 3
Example 8-9 shows how to print individual values of an array.
(ladebug) list 1, 4 1 main() { 2 int c[5],d; 3 for (d=0 ; d<=5 ; d++) { 4 c[d] = d; (ladebug) stop in main [#1: stop in main ] (ladebug) run [1] stopped at [main:3 0x1200010b4] 3 for (d=0 ; d<=5 ; d++) { (ladebug) whatis c array [subrange 0 ... 4 of int] of int c (ladebug) print c [0] = 0,[1] = 0,[2] = -2147474264,[3] = 1023,[4] = 0 (ladebug) step stopped at [main:4 0x120001068] 4 c[d]=d; (ladebug) <Return> stopped at [main:6 0x1200010dc] 6 } (ladebug) print c [0] = 0,[1] = 1,[2] = 2,[3] = 3,[4] = 4 (ladebug) print c[4] 4 (ladebug)
Expressions containing labels are not supported. Variables involving static anonymous unions and enumerated types cannot be printed. Printing a structure that is declared but not defined in a compilation unit generates an error message indicating that the structure is opaque.
Variables containing addresses are called pointers. By dereferencing a pointer, you can print the value at the address pointed to by the pointer. In C programs, variables containing a pointer are dereferenced using the * operator. Example 8-10 shows how to dereference a pointer in C programs.
(ladebug) list 1 1 main() 2 { 3 int x, *c; 4 5 c = &x; 6 x = 2; 7 *c = 0; 8 } (ladebug) stop in main [#1: stop in main ] (ladebug) run [1] stopped at [main:5 0x12000045c] 5 c = &x; (ladebug) whatis c int * c (ladebug) print c 0x11ffffe4c (ladebug) print *c 2 (ladebug)
The dump
command lists an active function's local
variables and parameters. You can specify a dump of a specific
function by naming the function as an argument to the command. You
can show all the variables and parameters in all currently active
functions by entering a period after the dump
command.
In Example 8-11, you obtain a dump of all
active functions from the sample program in Example 7-9.
(ladebug) dump >0 0x120001224 in factorial(i=1) sample.c:13 i=1 f=0 (ladebug)
The function factorial
has the parameter i
but it has no local variables. The function main
has two local variables, i
and f.
Your program may declare a particular symbol more than once. For
example, in the program sample.c
the symbol i
is declared in the function main
and again in
the function factorial.
Because the debugger extends the visibility and scope rules of
the programming language, the debugger may have access to more
than one declaration of a symbol name. You can use the which
command to determine which declaration exists in the current
context. The which
command displays the variable with
its scope information fully qualified.
The whereis
command lists all declarations of a
variable together with each declaration's scope information fully
qualified. Example 8-12 shows how to
use the whereis
and which
commands to
determine a variable's scope.
(ladebug) where >0 0x120001230 in factorial(i=1) sample.c:14 #1 0x12000124c in factorial(i=2) sample.c:16 #2 0x120001194 in main() sample.c:5 (ladebug) print i 1 (ladebug) which i "sample.c"`factorial.i (ladebug) whereis i "sample.c"`factorial.i "sample.c"`main.i (ladebug) func main main in sample.c line No. 5: 5 f = factorial(i); (ladebug) print i 2 (ladebug) which i "sample.c"`main.i (ladebug)
The whereis
command is useful for obtaining
information needed to differentiate overloaded identifiers that are
in different units, or within different routines in the same unit.
Example 8-13 shows how to set
breakpoints in two Ada program routines, both named DO_
PRINT.
(ladebug) whereis do_print "overload.ada"`OVERLOAD`DO_PRINT "overload.ada"`OVERLOAD`INNER`DO_PRINT (ladebug) stop in "overload.ada"`OVERLOAD`DO_PRINT [#1: stop in DO_PRINT ] (ladebug) stop in "overload.ada"`OVERLOAD`INNER`DO_PRINT [#2: stop in DO_PRINT ] (ladebug)
Use the assign
command to change the value associated
with an expression in the debugger session. The new value is
associated with the variable until the value is changed by the
program during execution, or until you specifically change the
value. The syntax for the assign
command is as
follows:
assign expression = expression
The expression argument can be any expression that is valid in the current context and language.
Example 8-14 shows how to deposit the
value -42
into the data item SUB-2
of a
COBOL program named TESTA.
(ladebug) assign sub-2=-42 (ladebug) print sub-2 -42
Example 8-15 shows how to change the value associated with a variable and the value associated with an expression.
(ladebug) assign i = 5 (ladebug) print i 5 (ladebug) assign f = factorial(8) 1 (ladebug) print f 40320 (ladebug) assign i = f (ladebug) print i 40320 (ladebug)
factorial.
Use the patch
command to change the value associated
with an expression in the object file on the disk as well as the
debugger process you are running. The syntax is as follows:
patch expression1 = expression2
The expression argument can be any expression that is valid in the current context and language.
The patch
command patches executable disk files to
correct bad data or instructions. The text, initialized data, or
read-only data areas can be patched. The bss
segment
cannot be patched because it does not exist in disk files.
For more information, see Chapter 22 and Part V, Command Reference.