Using Debug (continued) [ HP COBOL II/XL Programmer's Guide ] MPE/iX 5.0 Documentation
HP COBOL II/XL Programmer's Guide
Using Debug (continued)
Debugging Trap Errors
Debugging trap errors is easier if you have symbol table, verb, and link
maps of your program.
The trap error message contains the program counter (pc) address. In the
link map, find the value of the pc. The subprogram in which the trap
error occurred is the symbol of type code with the greatest SYM VALUE not
greater than the pc value. Subtract that SYM VALUE from the pc value to
get the offset of the trap.
In the verb map for the subprogram in which the trap occurred, find the
statement with the greatest offset not greater than the offset of the
trap. This is the statement where the trap occurred.
If the subprogram in which the trap occurred is not written in COBOL, the
error message may be misleading. However, the pc value, link map, and
stack marker trace (which is printed when the program aborts) are
accurate.
If you get the system trap error message DATA MEMORY PROTECTION or
INVALID ADDRESS, recompile your COBOL program with the control option
BOUNDS and rerun it. You will probably get a COBOL trap, because these
system traps usually result from values out of bounds.
This section gives at least one debugging example for each type of trap.
The types of traps are:
* Illegal ASCII or Decimal Digit.
* Range Error.
* No Size Error.
* PERFORM Stack Overflow.
* Invalid GO TO.
* Address Alignment.[REV BEG]
* Intrinsic Function Traps.[REV END]
This section also explains:
* Trace traps.
Redirecting Output from Traps.
The trap examples that follow show output that goes to $STDLIST. The
output comes from two sources, the COBOL run-time library and Debug.[REV
BEG] [REV END]
[REV BEG]
NOTE The examples that follow print the statement number of the trap as
Stmt #nnn
However, for optimized programs, the statement number appears as
????.
This also occurs for statements that generate a large amount of
machine instructions. In such cases, see the section "Calculating
Code Addresses" in this chapter to determine the statement where
the error occurs.
[REV END]
Illegal ASCII Digit.
In this example, a program with illegal ASCII digits is executed with the
COBRUNTIME value A. The effect of other COBRUNTIME values is explained
after the example.
Given the following compiled source program:
00001 000100$CONTROL MAP,VALIDATE
00003 001000 IDENTIFICATION DIVISION.
00004 002000 PROGRAM-ID. TRAP-ASCII-DIG.
00005 003000 DATA DIVISION.
00006 004000 WORKING-STORAGE SECTION.
00007 005000 01 BAD-VALUE PIC X(4) VALUE "12 4".
00008 006000 01 B REDEFINES BAD-VALUE PIC 9(4).
00009 007000 01 D PIC 9(4).
00010 008000 PROCEDURE DIVISION.
00011 009000 TRAP-TEST.
00012 009100******************************************
00013 009200* Trap test with illegal ASCII digit *
00014 009300******************************************
00015 010000 DISPLAY "Should produce illegal ASCII digit.".
00016 011000 ADD 1 TO B.
00017 012000 DISPLAY BAD-VALUE.
00018 013000 DISPLAY "Test case did not abort.".
00019 014000 STOP RUN.
The section of the map that shows the addresses of items in
WORKING-STORAGE is:
[REV BEG]
LINE# LVL SOURCE NAME BASE OFFSET SIZE USAGE CATEGORY
WORKING-STORAGE SECTION
00007 01 BAD-VALUE DP+ 30 4 DISP AN
00008 01 B DP+ 30 4 DISP N
00009 01 D DP+ 34 4 DISP N
[REV END]
When COBRUNTIME is not set (that is, when it has its default value) or
when COBRUNTIME is set to A (Abort), and the program is compiled with the
control option VALIDATE, this program produces the following information
when run in session mode. (When run in a job stream, the output may look
slightly different. When debugging a program, running it in a session is
recommended.)
:$OLDPASS
Should produce illegal ASCII digit.
Illegal ASCII digit (COBERR 711)
Program file: $OLDPASS.H6OPT2.COBOL74
Trap type = 00000200 (22,00), at pc = 000004D0.000083BF
invalid ascii digit
Source address = 40200030, Source = '12 4'
(hex) Source = '31322034'
DEBUG/XL A.01.00
HPDEBUG Intrinsic at: 4d0.0000d1fc print_message$093+$314
$$$$ Trap occurred at: trap_ascii_dig+$74, at Stmt #16
PC=4d0.00007ac0 vloop+$c
0) SP=402210e8 RP=4d0.000083c4 trap_ascii_dig+$7c
* 1) SP=402210e8 RP=4d0.00000000 inx_A0000+$14
(end of NM stack)
$$$$ The address $40200030 = DP+$28 may be in main, SUBPROGRAM or EXTERNAL
The most important pieces of information are flagged by the string
"$$$$." The first gives you the number of the statement that preceded the
trap. The second gives you the address of the data item that caused the
trap. If you look up DP+$28 in the map, you find that the data item
BAD-VALUE caused this trap. (Since the output above says that the data
item that caused the trap could be in a main program, be in a subprogram,
or be an EXTERNAL item, you must study the maps and data of your program
to determine that BAD-VALUE is the culprit. The statement number (#16)
may also help determine the problem.)
Beneath the line flagged "$$$$" above is a stack trace that shows where
in your code the program aborted. The highest name on this stack that is
the name of one of your programs has the exact address in the program
file where the abort occurred. This may be useful if you use Debug.
Refer to the MPE XL System Debug Reference Manual for more information.
If you change the value of COBRUNTIME and rerun the above program,
program behavior changes as described below.
COBRUNTIME Value Change in Program Behavior
I The trap occurs, but the program ignores it and
continues.
M The trap occurs, the above trap information is
printed, the illegal digit is replaced by a
legal digit, and the program continues.
N The trap occurs, the illegal digit is replaced
by a legal digit, and the program continues.
C The trap occurs, the above trap information is
printed, and the program continues.
[REV BEG]
The following example shows an illegal ASCII digit error with an invalid
sign. The error occurs when attempting to display variables N4 and N4R.
C
PAGE 0001 COBOL II/XL HP31500A.04.03 [85] TUE, JUL 9, 1991, 5:18
PM Copyright Hewlett-Packard CO. 1987
00001 001000$CONTROL VALIDATE
00002 001100 IDENTIFICATION DIVISION.
00003 001200 PROGRAM-ID.
00004 001300 COBMAIN.
00005 001400 ENVIRONMENT DIVISION.
00006 001500 DATA DIVISION.
00007 001600 WORKING-STORAGE SECTION.
00008 001700 01 A1 PIC X VALUE SPACES.
00009 001800 01 N1 PIC 99 VALUE 0.
00010 001900 01 N2 PIC 99 VALUE 0.
00011 002000 01 N3 PIC S99 VALUE 0.
00012 002010 01 N4 PIC 999.
00013 002020 01 N4R REDEFINES N4 PIC S999.
00014 002100 PROCEDURE DIVISION.
00015 002200 FIRST-PARA.
00016 002300 MOVE 10 TO N1.
00017 002400 MOVE N1 TO N3.
00018 002500 DISPLAY N1, N3.
00019 002510 MOVE 111 TO N4.
00020 002520 DISPLAY N4, N4R.
00021 002600 STOP RUN.
0 ERROR(s), 0 QUESTIONABLE, 0 WARNING(s)
DATA AREA IS 44 BYTES.
CPU TIME = 0:00:01. WALL TIME = 0:00:01.
[REV END]
[REV
BEG]
10+10
Illegal ASCII digit (COBERR 711)
Program file: $OLDPASS.USER2.COBOL74
Trap type = 00000200 (22,01), at pc = 000000B9.00005E07
invalid ascii digit (S->S)
Source address = 4033A0BC, Source = '111'
(hex) Source = '313131'
DEBUG/XL A.47.01
HPDEBUG Intrinsic at: 678.00351270 cob_trap.print_message+$5c4
$$$$ Trap occurred at: cobmain+$1b4, at Stmt #20
PC=b9.00005e04 cobmain+$1b4
* 0) SP=4033a0f0 RP=b9.00000000 $$inx_A0000+$14
(end of NM stack)
$$$$ The address $4033a0bc = SP-$34 is in cobmain (TEMPCELL or $DYNAMIC)
============================================================
**** COB_QUIT 711 ****
ABORT: $OLDPASS.USER2.COBOL74
NM SYS a.00944414 dbg_abort_trace+$2c
NM USER 678.003502f8 COB_QUIT+$b8
NM SYS a.004403d0 user_trap_caller+$e4
--- Interrupt Marker
NM PROG b9.00005e04 cobmain+$1b4
[REV END]
Range Error.
These errors may occur when a subscript or index references an array out
of bounds.
Given the following compiled source program:
00001 001000$CONTROL BOUNDS,MAP
00003 001100 IDENTIFICATION DIVISION.
00004 001200 PROGRAM-ID. BOUNDSEXAMPLE.
00005 001300* This program has a subscript out of bounds.
00006 001400 DATA DIVISION.
00007 001500 WORKING-STORAGE SECTION.
00008 001600 01.
00009 001700 05 PIC X.
00010 001800 05 XX PIC X.
00011 001900 01.
00012 002000 05 Y OCCURS 80 TIMES PIC X.
00013 002100 01 Z PIC S9(9) COMP VALUE 0.
00014 002200 PROCEDURE DIVISION.
00015 002300 P1.
00016 002400**************************************************
00017 002500* Trap test with range error *
00018 002600**************************************************
10019 002700 MOVE -5 TO Z.
00020 002800 MOVE Y(Z) TO XX.
00021 002900 DISPLAY "Test case did not abort.".
00022 003000 STOP RUN.
The section of the map that shows the addresses of items in
WORKING-STORAGE is:
LINE# LVL SOURCE NAME BASE OFFSET SIZE USAGE CATEGORY
WORKING-STORAGE SECTION
00008 01 FILLER DP+ 28 2 DISP AN
00009 05 FILLER DP+ 28 1 DISP AN
00010 05 XX DP+ 29 1 DISP AN
00011 01 FILLER DP+ 2C 50 DISP AN
00012 05 Y DP+ 2C 1 DISP AN
00013 01 Z DP+ 7C 4 COMP NS
When COBRUNTIME is not set (that is, when it has its default value) or
when COBRUNTIME is set to A (Abort), and the program is compiled with the
control option BOUNDS, this program produces the following information
when run in a session. (When run in a job stream, the output may look
slightly different. When debugging a program, running it in a session is
recommended.)
:$OLDPASS
SUBSCRIPT/INDEX/REFMOD/DEP-ON out of BOUNDS (COBERR 751)
Program file: $OLDPASS.H6OPT2.COBOL74
Trap type = 00080000 (12,00), at pc = 00000551.000077CB
range error
DEBUG/XL A.01.00
HPDEBUG Intrinsic at: 551.0000c594 print_message$093+$314
$$$$ Trap occurred at: boundsexample+$30, at Stmt #20
PC=551.000077c8 boundsexample+$30
* 0) SP=402210d8 RP=551.00000000
(end of NM stack)
$$$$ The variable -5 < 1 (limit)
The most important pieces of information are flagged by the string
"$$$$." The first gives you the number of the statement that preceded the
trap. The second gives you the bad value of the index or subscript,
compared to the limit.
Beneath the line flagged "$$$$" above is a stack trace that shows where
in your code the program aborted. The highest name on this stack that is
the name of one of your programs has the exact address in the program
file where the abort occurred. This may be useful if you use Debug.
Refer to the MPE XL System Debug Reference Manual for more information.
No Size Error.
The No Size Error trap sometimes occurs where it is not possible to
specify ON SIZE ERROR, as in an expression in a relational condition. If
the same expression were in a COMPUTE statement, the ON SIZE ERROR phrase
would execute.
In the following compiled source program, division by zero causes the ON
SIZE ERROR trap:
0001 001000 identification division.
0002 001100 program-id. zerotrap.
0003 001200 data division.
0004 001300 working-storage section.
0005 001400 77 n pic 999.
0006 001500 77 bad-value pic s999 value zero.
0007 001600 procedure division.
0008 001700 house.
0009 001800*********************************************
0010 001900* Divide by Zero with no Size Error Phrase. *
0011 002000*********************************************
0012 002100 Display "Should give NO SIZE ERROR PHRASE".
0013 002200 Compute n = 1 / BAD-VALUE.
0014 002300 Display "Test case did not abort".
0015 002400 Stop run.
When COBRUNTIME is not set (that is, when it has its default value) or
when COBRUNTIME is set to A (Abort), this program produces the following
information when run in a session. (When run in a job stream, the output
may look slightly different. When debugging a program, running it in a
session is recommended.)
:$OLDPASS
Should give NO SIZE ERROR PHRASE
No SIZE ERROR phrase (COBERR 747)
Program file: $OLDPASS.H6OPT2.COBOL74
Trap type = 00000002 (30,00), at pc = 00000531.0000835B
integer divide by 0
DEBUG/XL A.01.00
HPDEBUG Intrinsic at: 531.0000d124 print_message$093+$314
$$$$ Trap occurred at: zerotrap+$a0, at Stmt #13
PC=531.00006774 small_divisor+$8
0) SP=402210f0 RP=531.00008360 zerotrap+$a8
* 1) SP=402210f0 RP=531.00000000 inx_A0000+$14
(end of NM stack)
The most important piece of information is flagged by the string "$$$$,"
which tells you the number of the statement that preceded the trap.
Beneath the line flagged "$$$$" above is a stack trace that shows where
in your code the program aborted. The highest name on this stack that is
the name of one of your programs has the exact address in the program
file where the abort occurred. This can be useful if you use Debug.
Refer to the MPE XL System Debug Reference Manual for more information.
PERFORM Stack Overflow.
Each program has a PERFORM stack, used to keep track of which paragraphs
are executing and where to return after execution of a paragraph. This
stack can overflow if your program has control-flow bugs, as the
following example does. It has recursive PERFORM statements.
Given the following compiled source program:
00001 001000$CONTROL BOUNDS,VERBS
00003 001100 IDENTIFICATION DIVISION.
00004 001200 PROGRAM-ID. PERFORM-TRAP.
00005 001300 PROCEDURE DIVISION.
00006 001400 TRAP-TEST.
00007 001500 DISPLAY "Should give paragraph stack overflow.".
00008 001600******************************************
00009 001700* Trap test with recursive performs. *
00010 001800******************************************
00011 001900 PERFORM PAR-A THROUGH PAR-B.
00012 002000 GO TO COMMON-EXIT.
00013 002100 PAR-A.
00014 002200 PERFORM PAR-B.
00015 002300 PAR-B.
00016 002400 PERFORM PAR-A.
00017 002500 COMMON-EXIT.
00018 002600 DISPLAY "Test case did not abort.".
00019 002700 STOP RUN.
Here is the verb map that shows the code offsets of the program
statements:
PAGE 0002/COBTEXT PERFORM-TRAP STATEMENT OFFSETS
Entry = perform_trap
STMT OFFSET STMT OFFSET STMT OFFSET STMT OFFSET ...
6 3C 12 80 15 B4 18 E0
7 3C 13 88 16 B4 19 110
11 68 14 88 17 E0
When COBRUNTIME is not set (that is, when it has its default value) or
when COBRUNTIME is set to A (Abort), and the program is compiled with the
control option BOUNDS, this program produces the following information
when run in a session. (When run in a job stream, the output may look
slightly different. When debugging a program, running it in a session is
recommended.)
:$OLDPASS
Should give paragraph stack overflow.
Paragraph stack overflow (COBERR 748)
Program file: $OLDPASS.H6OPT2.COBOL74
Trap type = 00800000 (08,00), at pc = 00000531.00007873
paragraph stack overflow
DEBUG/XL A.01.00
HPDEBUG Intrinsic at: 531.0000c64c print_message$093+$314
$$$$ Trap occurred at: perform_trap+$b8, at Stmt #16
PC=531.00007870 perform_trap+$b8
* 0) SP=40221278 RP=531.00000000
(end of NM stack)
Perform stack for COBOL program: perform_trap+$b8
Return at end of procedure #2 to perform_trap+$a0 Stmt #14
Return at end of procedure #1 to perform_trap+$cc Stmt #16
Return at end of procedure #2 to perform_trap+$a0 Stmt #14
Return at end of procedure #1 to perform_trap+$cc Stmt #16
Return at end of procedure #2 to perform_trap+$a0 Stmt #14
Return at end of procedure #1 to perform_trap+$cc Stmt #16
:
Return at end of procedure #1 to perform_trap+$cc Stmt #16
Return at end of procedure #2 to perform_trap+$a0 Stmt #14
Return at end of procedure #2 to perform_trap+$80 Stmt #11
End of perform stack
The statement number preceding the trap is flagged by the string "$$$$"
and the contents of the PERFORM stack is printed. The phrase "Return at
end of procedure #num" means that the paragraph[REV BEG] num has been
called, where paragraph zero is the first paragraph in the source
program, paragraph one[REV END] is the second, and so on. (When sections
are called, the number of the last paragraph in the section appears.)
This PERFORM stack trace also tells you from where the paragraph was
called: that is the statement number on the far right.
Beneath the line flagged "$$$$" above is a stack trace that shows where
in your code the program aborted. The highest name on this stack that is
the name of one of your programs has the exact address in the program
file where the abort occurred. This can be useful if you use Debug.
Refer to the MPE XL System Debug Reference Manual for more information.
Invalid GO TO.
This example illustrates an invalid GO TO trap, which occurs at an
unaltered GO TO statement:
00001 001000$CONTROL BOUNDS
00002 001100 IDENTIFICATION DIVISION.
00003 001200 PROGRAM-ID. TRAPGOTO.
00004 001300 PROCEDURE DIVISION.
00005 001400 TRAP-TEST.
00006 001500*******************************************
00007 001600* Trap test with Invalid Goto *
00008 001700*******************************************
00009 001800 DISPLAY "Should produce illegal goto trap.".
00010 001900 PAR.
00011 002000 GO TO.
00012 002100 PAR2.
00013 002200 ALTER PAR TO PAR2.
00014 002300 COMMON-EXIT.
00015 002400 DISPLAY "Test case did not abort.".
00016 002500 STOP RUN.
When COBRUNTIME is not set (that is, when it has its default value) or
when COBRUNTIME is set to A (Abort), and the program is compiled with the
control option BOUNDS, this program produces the following information
when run in a session. (When run in a job stream, the output may look
slightly different. When debugging a program, running it in a session is
recommended.)
:$OLDPASS
Should produce illegal goto trap.
Invalid GOTO (COBERR 754)
Program file: $OLDPASS.H6OPT2.COBOL74
Trap type = 00100000 (11,00), at pc = 00000551.00007817
nil pointer reference
DEBUG/XL A.01.00
HPDEBUG Intrinsic at: 551.0000c5ec print_message$093+$314
$$$$ Trap occurred at: trapgoto+$54, at Stmt #11
PC=551.00007814 trapgoto+$54
* 0) SP=402210d8 RP=551.00000000
(end of NM stack)
The most important piece of information is flagged by the string "$$$$."
It tells you the statement number of the unaltered GO TO statement.
Beneath the line flagged "$$$$" above is a stack trace that shows where
in your code the program aborted. The highest name on this stack that is
the name of one of your programs has the exact address in the program
file where the abort occurred. This can be useful if you use Debug.
Refer to the MPE XL System Debug Reference Manual for more information.
Address Alignment.
Address alignment traps are caught by the Link Editor. You must link
with PARMCHECK=0 AND purposely ignore the Link Editor warnings to cause
one of these traps.
This example illustrates parameter misalignment, where a parameter is
passed to a COBOL subprogram that is not 32-bit aligned:
00001 001000$CONTROL MAP
00002 001100 IDENTIFICATION DIVISION.
00003 001200 PROGRAM-ID. TRAPMAIN.
00004 001300 DATA DIVISION.
00005 001400 WORKING-STORAGE SECTION.
00006 001500 01.
00007 001600 05 PIC X.
00008 001700 05 XX PIC X.
00009 001800 PROCEDURE DIVISION.
00010 001900 P1.
00011 002000******************************************
00012 002100* Trap tests with alignment *
00013 002200******************************************
00014 002300 DISPLAY "Should produce alignment trap.".
00015 002400 CALL "Trapsub" USING XX.
00016 002500 DISPLAY "Test case did not abort.".
00017 002600 STOP RUN.
This subsection of the map shows the addresses of items in
WORKING-STORAGE. Notice that parameter XX is on an odd byte boundary
(DP+29).
LINE# LVL SOURCE NAME BASE OFFSET SIZE USAGE CATEGORY
WORKING-STORAGE SECTION
00006 01 FILLER DP+ 28 2 DISP AN
00007 05 FILLER DP+ 28 1 DISP AN
00008 05 XX DP+ 29 1 DISP AN
COBOL subprograms normally assume worst case (byte) alignment, which
should never trap. To cause an address alignment trap, you must do one
more thing: compile the subprogram with OPTFEATURES = LINKALIGNED
(this option generates faster code, which assumes parameters are
32-bit-aligned).
Here is the compiled subprogram, called by the above main program:
00001 001000$CONTROL MAP,SUBPROGRAM,BOUNDS
00003 001100$CONTROL OPTFEATURES=LINKALIGNED
00003 001200 IDENTIFICATION DIVISION.
00004 001300 PROGRAM-ID. TRAPSUB.
00005 001400 DATA DIVISION.
00006 001500 LINKAGE SECTION.
00007 001600 01 XX PIC X.
00008 001700 PROCEDURE DIVISION USING XX.
00009 001800 P1.
00010 001900 MOVE "**" TO XX.
00011 002000 EXIT PROGRAM.
LINE# LVL SOURCE NAME BASE OFFSET SIZE USAGE CATEGORY
LINKAGE SECTION
00007 01 XX P 00 0 1 DISP AN
Here is the link command, with parameter checking turned off (if
parameter checking is not turned off, the link fails to produce a program
file):
:link from=strapm,straps;to=ptrapm;PARMCHECK=0
HP Link Editor/XL (HP30315A.00.23) Copyright Hewlett-Packard Co 1986
LinkEd> link from=strapm,straps;to=ptrapm;PARMCHECK=0
INCOMPATIBLE ALIGNMENT: trapsub (STRAPM, STRAPS) (LINKWARN 1504)
(PARAMETER #1)
The Link Editor tells you which program is being called with the bad
parameter.
When COBRUNTIME is not set (that is, when it has its default value) or
when COBRUNTIME is set to A (Abort), this program produces the following
information when run in a session. (When run in a job stream, the output
may look slightly different When debugging a program, running it in a
session is recommended.)
:ptrapm
SHOULD PRODUCE ALIGNMENT TRAP (753)
Address alignment error (COBERR 753)
Program file: PTRAPM.H6OPT2.COBOL74
Trap type = 00200000 (10,00), at pc = 000004D0.0000790F
bad address alignment
DEBUG/XL A.01.00
HPDEBUG Intrinsic at: 4d0.0000c724 print_message$093+$314
$$$$ Trap occurred at: trapsub+$4c, at ????
PC=4d0.0000790c trapsub+$4c
* 0) SP=402212b8 RP=4d0.00007814 trapmain+$54
1) SP=402210d8 RP=4d0.00000000
(end of NM stack)
$$$$ Called from: trapmain+$54, at Stmt #15
$$$$ The address $40200031 = DP+$29 may be in main, SUBPROGRAM or EXTERNAL
The lines with "$$$$" in the above example indicate: the program where
the abort occurred (trapsub), the address in the program with the CALL
statement (trapmain), and the address (DP+$29) of the data item in
question.
MPE/iX 5.0 Documentation