Previous | Contents | Index |
The SHOW CALLS command lets you determine the current value of the program counter (PC) (for example, after returning to the debugger following a Ctrl/y interruption).
The SHOW CALLS command displays a traceback that lists the sequence of calls leading to the currently executing routine. For each routine (beginning with the currently executing routine), the debugger displays the following information:
For example:
DBG> SHOW CALLS module name routine name line rel PC abs PC *TEST PRODUCT 18 00000009 0000063C *TEST COUNT 47 00000009 00000647 *MY_PROG MY_PROG 21 0000000D 00000653 DBG> |
The SET BREAK command lets you select breakpoints, which are locations at which program execution is suspended. When you reach a breakpoint, you can issue commands to check the call stack, examine the current values of variables, and so on.
In the following example, the SET BREAK command sets a breakpoint on the procedure COUNT. The GO command then starts execution. When the procedure COUNT is encountered, execution is suspended. The debugger reports that the breakpoint at COUNT has been reached (break at ...), displays the source line (54) where execution is suspended, and prompts you for another command. At this breakpoint, you could step through the procedure COUNT, using the STEP command, and use the EXAMINE command (discussed in Section 3.3.6.1) to check on the current values of X and Y.
DBG> SET BREAK COUNT DBG> GO . . . break at PROG2\COUNT 54: COUNT: PROCEDURE (X,Y); DBG> |
When using the SET BREAK command, you can specify program locations using various kinds of address expressions (for example, line numbers, routine names, instructions, virtual memory addresses, or byte offsets). With high-level languages, you typically use routine names, labels, or line numbers, possibly with path names to ensure uniqueness.
Routine names and labels should be specified as they appear in the source code. Line numbers may be derived from either a source code display or a listing file. When specifying a line number, use the prefix %LINE. (Otherwise, the debugger interprets the line number as a memory location.) For example, the next command sets a breakpoint at line 41 of the module whose code is currently executing; the debugger suspends execution when the PC value is at the start of line 41.
DBG> SET BREAK %LINE 41 |
Note that you can set breakpoints only on lines that resulted in machine code instructions. The debugger warns you if you try to do otherwise (for example, if you try to set a breakpoint on a comment line). To set a breakpoint on a line number in a module other than the one whose code is currently executing, specify the module's name in a path name. For example:
DBG> SET BREAK SCREEN_IO\%LINE 58 |
You do not always need to specify a particular program location, such as line 58 or COUNT, to set a breakpoint. You can set breakpoints on events, such as exceptions. You can also use the SET BREAK command with the /LINE qualifier (but no parameter) to break on every line, or with the /CALL qualifier to break on every CALL instruction, and so on. For example:
DBG> SET BREAK/LINE DBG> SET BREAK/CALL |
You can conditionalize a breakpoint (with a WHEN clause) or specify that a list of commands be executed at the breakpoint (with a DO clause). For example, the next command sets a breakpoint on the label LOOP3. The DO (EXAMINE TEMP) clause causes the value of the variable TEMP to be displayed whenever the breakpoint is triggered.
DBG> SET BREAK LOOP3 DO (EXAMINE TEMP) DBG> GO . . . break at COUNTER\LOOP3 37: LOOP3: DO I = 1 TO 10 COUNTER\TEMP: 284.19 DBG> |
To display the currently active breakpoints, issue the SHOW BREAK command:
DBG> SHOW BREAK breakpoint at SCREEN_IO\%LINE 58 breakpoint at COUNTER\LOOP3 do (EXAMINE TEMP) . . . DBG> |
If any portion of your program was written in Ada, two breakpoints that are associated with Ada tasking exception events are automatically established when you invoke the debugger. When you issue a SHOW BREAK command under these conditions, the following breakpoints are displayed:
DBG> SHOW BREAK Breakpoint on ADA event "DEPENDENTS_EXCEPTION" for any value Breakpoint on ADA event "EXCEPTION_TERMINATED" for any value |
These breakpoints are equivalent to issuing the following commands:
DBG> SET BREAK/EVENT=DEPENDENTS_EXCEPTION DBG> SET BREAK/EVENT=EXCEPTION_TERMINATED |
To cancel a breakpoint, issue the CANCEL BREAK command, specifying the
program location or event exactly as you did when setting the
breakpoint. The CANCEL BREAK/ALL command cancels all breakpoints.
3.3.5.4 Tracing Program Execution
The SET TRACE command lets you select tracepoints, which are locations for tracing the execution of your program without stopping its execution. After setting a tracepoint, you can start execution with the GO command and then monitor the path of execution, checking for unexpected behavior. By setting a tracepoint on a routine, you can also monitor the number of times the routine is called.
As with breakpoints, every time a tracepoint is reached, the debugger issues a message and displays the source line. However, at tracepoints, the program continues executing, and the debugger prompt is not displayed. For example:
DBG> SET TRACE COUNT DBG> GO . . . trace at PROG2\COUNT 54: COUNT: PROCEDURE (X,Y); . . . |
When using the SET TRACE command, specify address expressions, qualifiers, and optional clauses exactly as with the SET BREAK command.
The /LINE qualifier causes the SET TRACE command to trace every line and is a convenient means of checking the execution path. By default, lines are traced within all called routines, as well as the currently executing routine. If you do not want to trace through system routines or through routines in shareable images, use the /NOSYSTEM or /NOSHARE qualifiers. For example:
DBG> SET TRACE/LINE/NOSYSTEM/NOSHARE |
The /SILENT qualifier suppresses the trace message and the display of source code. This is useful when you want to use the SET TRACE command to execute a debugger command at the tracepoint. For example:
DBG> SET TRACE/SILENT %LINE 83 DO (EXAMINE STATUS) DBG> GO . . . SCREEN_IO\CLEAR\STATUS: 'OFF' . . . |
The SET WATCH command lets you set watchpoints that will be monitored continuously as your program executes. With high-level languages, you typically set watchpoints on variables that have been declared in your program. In addition, you can set watchpoints on arbitrary program locations. If the program modifies the value of a watched variable, the debugger suspends execution and displays the old and new values.
To set a watchpoint on a variable, specify the variable's name with the SET WATCH command. For example, the following command sets a watchpoint on the variable TOTAL:
DBG> SET WATCH TOTAL |
Subsequently, every time the program modifies the value of TOTAL, the watchpoint is triggered.
The following example shows the effect on program execution when your program modifies the contents of a watched variable.
DBG> SET WATCH TOTAL DBG> GO . . . watch of SCREEN_IO\TOTAL at SCREEN_IO\%LINE 13 13: TOTAL = TOTAL + 1; old value: 16 new value: 17 break at SCREEN_IO.%LINE 14 14: POP(TOTAL); DBG> |
In this example, a watchpoint is set on the variable TOTAL, and the GO command is issued to start execution. When the value of TOTAL changes, execution is suspended. The debugger reports the event watch of ... and identifies where TOTAL changed (line 13) and the associated source line. The debugger then displays the old and new values and reports that execution has been suspended at the start of the next line (14). (The debugger reports break at ..., but this is not a breakpoint; it is the effect of the watchpoint.) Finally, the debugger prompts for another command.
When a change in a variable occurs at a point other than at the start of a source line, the debugger gives the line number plus the byte offset from the start of the line.
Note that this general technique for setting watchpoints always applies to static variables. A static variable is associated with the same virtual memory location throughout program execution. In PL/I, only the following kinds of variables are statically allocated:
A variable that is allocated on the stack or in a register (a nonstatic variable) exists only when its defining routine is active (on the call stack). In PL/I nonstatic variables include the following:
If you try to set a watchpoint on a nonstatic variable when its defining routine is not active, the debugger issues a warning like the following:
DBG> SET WATCH Y %DEBUG-W-SYMNOTACT, nonstatic variable 'Y' is not active |
A convenient technique for setting a watchpoint on a nonstatic variable is to set a breakpoint on the defining routine, also specifying a DO clause to set the watchpoint whenever execution reaches the breakpoint. In the following example, a watchpoint is set on the nonstatic variable Y in routine COUNTER:
DBG> SET BREAK COUNTER DO (SET WATCH Y) DBG> GO . . . break at routine MOD4\COUNTER %DEBUG-I-WPTTRACE, nonstatic watchpoint, tracing every instruction DBG> SHOW WATCH watchpoint of MOD4\COUNTER\Y [tracing every instruction] DBG> |
The debugger monitors nonstatic watchpoints by tracing every instruction. Because this slows execution speed compared to monitoring static watchpoints, the debugger informs you when it is monitoring nonstatic watchpoints.
When execution eventually returns to the calling routine, the nonstatic
variable is no longer active, so the debugger automatically cancels the
watchpoint and issues a message to that effect.
3.3.6 Examining and Manipulating Data
This section explains how to use the EXAMINE, DEPOSIT, and EVALUATE commands to display and modify the contents of variables and to evaluate expressions. It also notes restrictions on the use of these commands with PL/I programs.
Note that, before you can examine or deposit into a nonstatic variable
(as defined in the previous section), its defining routine must be
active (on the call stack).
3.3.6.1 Displaying the Values of Variables
To display the current value of a variable, use the EXAMINE command. The EXAMINE command has the following form:
EXAMINE variable-name |
The debugger recognizes the compiler-generated data type of the specified variable and retrieves and formats the data accordingly. The following examples show some uses of the EXAMINE command.
Examine a string variable:
DBG> EXAMINE EMPLOYEE_NAME PAYROLL\EMPLOYEE_NAME: "Peter C. Lombardi" DBG> |
Examine three integer variables:
DBG> EXAMINE WIDTH, LENGTH, AREA SIZE\WIDTH: 4 SIZE\LENGTH: 7 SIZE\AREA: 28 DBG> |
Examine a two-dimensional array of integers (three per dimension):
DBG> EXAMINE INTEGER_ARRAY PROG2\INTEGER_ARRAY (1,1): 27 (1,2): 31 (1,3): 12 (2,1): 15 (2,2): 22 (2,3): 18 DBG> |
Examine element 4 of a one-dimensional array of characters:
DBG> EXAMINE CHAR_ARRAY(4) PROG2\CHAR_ARRAY(4): "m" DBG> |
Examine the value of a variable declared as FIXED DECIMAL (10,5):
DBG> EXAMINE X PROG4\X: 540.02700 DBG> |
Examine the value of a structure variable:
DBG> EXAMINE PART MAIN_PROG\INVENTORY_PROG.PART ITEM: "WF-1247" PRICE: 49.95 IN_STOCK: 24 DBG> |
Examine the value of a pictured variable (note that the debugger displays the value in quotation marks):
DBG> EXAMINE Q MAINP\Q: "666.3330" DBG> |
Examine the value of a pointer (which is the virtual address of the variable it accesses) and display the value in hexadecimal radix instead of decimal (the default):
DBG> EXAMINE/HEXADECIMAL P PROG4\SAMPLE.P: 0000B2A4 DBG> |
Examine the value of a variable with the BASED attribute; in this case, the variable X has been declared as BASED(PTR), with PTR its pointer:
DBG> EXAMINE X PROG5\X: "A" DBG> |
Examine the value of a variable X declared as BASED with a variable PTR declared as POINTER; here, PTR is associated with X by the following line of PL/I code (instead of X having been declared as BASED(PTR) as in the preceding example):
ALLOCATE X SET (PTR); |
DBG> EXAMINE PTR->X PROG6\PTR->X: "A" DBG> |
The EXAMINE command can be used with any kind of address expression, not just a variable name, to display the contents of a program location. The debugger associates certain default data types with untyped locations. You can override the defaults for typed and untyped locations if you want the data to be interpreted and displayed in some other data format.
See Section 3.3.6.3 for a comparison of the EXAMINE and EVALUATE commands.
3.3.6.2 Changing the Values of Variables
To change the value of a variable, use the DEPOSIT command. The DEPOSIT command has the following form:
DEPOSIT variable-name = value |
The DEPOSIT command is like an assignment statement in PL/I.
In the following examples, the DEPOSIT command assigns new values to different variables. The debugger checks that the value assigned, which can be a language expression, is consistent with the data type and dimensional constraints of the variable.
Deposit a string value (it must be enclosed in quotation marks or apostrophes):
DBG> DEPOSIT PARTNUMBER = "WG-7619.3-84" |
Deposit an integer expression:
DBG> DEPOSIT WIDTH = CURRENTWIDTH + 10 |
Deposit element 12 of an array of characters (you cannot deposit an entire array aggregate with a single DEPOSIT command, only an element):
DBG> DEPOSIT C_ARRAY(12) = 'K' |
As with the EXAMINE command, the DEPOSIT command lets you specify any
kind of address expression, not just a variable name. You can override
the defaults for typed and untyped locations if you want the data to be
interpreted in some other data format.
3.3.6.3 Evaluating Expressions
To evaluate a language expression, use the EVALUATE command. The EVALUATE command has the following form:
EVALUATE language-expression |
The debugger recognizes the operators and expression syntax of the currently set language. In the following example, the value 45 is assigned to the integer variable WIDTH; the EVALUATE command then obtains the sum of the current value of WIDTH plus 7:
DBG> DEPOSIT WIDTH = 45 DBG> EVALUATE WIDTH + 7 52 DBG> |
The following example shows how the EVALUATE and EXAMINE commands are similar. When the expression following the command is a variable name, the value reported by the debugger is the same for either command.
DBG> DEPOSIT WIDTH = 45 DBG> EVALUATE WIDTH 45 DBG> EXAMINE WIDTH SIZE\WIDTH: 45 |
The following example shows an important difference between the EVALUATE and EXAMINE commands:
DBG> EVALUATE WIDTH + 7 52 DBG> EXAMINE WIDTH + 7 SIZE\WIDTH: 131584 |
In general, the debugger supports the data types and operators of PL/I and of the other debugger-supported languages. However, there are certain language-specific limitations or other differences. (For information on the supported data types and operators of any of the languages, type the HELP LANGUAGE command at the DBG> prompt.)
You cannot use the DEPOSIT command with entry or label variables or formats, or with entire arrays or structures. You cannot use the EXAMINE command with entry or label variables or formats; use the EVALUATE/ADDRESS command instead.
You cannot use the EXAMINE command to determine the values or attributes of global literals (such as GLOBALDEF VALUE literals) because they are static expressions. Use the EVALUATE command instead.
You cannot use the EXAMINE, EVALUATE, and DEPOSIT commands with compile-time variables and procedures. You can, however, use EVALUATE and DEPOSIT (but not EXAMINE) with a compile-time constant, as long as the constant is the source and not the destination.
Note that an uninitialized automatic variable does not have valid contents until after a value has been assigned to it. If you examine it before that point, the value displayed is unpredictable.
You can deposit a value into a pointer variable either by depositing another pointer's value into it, thus making symbolic reference to both pointers, or by depositing a virtual address into it. (You can find out the virtual address of a variable by using the EVALUATE/ADDRESS command, and then deposit that address into the pointer.) When you examine a pointer, the debugger displays its value in the form of the virtual address of the variable that the pointer points to.
Because the default representation of decimal constants in PL/I is packed decimal rather than fixed binary, debugger commands such as EVALUATE/HEXADECIMAL 53 display the number's packed decimal representation. You can cause conversion to take place, however, either by specifying a fixed binary variable in the expression, or by using a constant in a radix other than decimal (because nondecimal radix constants are assumed to be fixed binary), as in the command:
EVALUATE/HEXADECIMAL 53 + %HEX 0. |
Previous | Next | Contents | Index |