Divide-by-zero error

Figure 1 illustrates a C program that contains a divide-by-zero error. The code was compiled with RENT so static and external variables need to be calculated from the WSA field. The code was compiled with LP64, GONUM (to produce statement numbers) and XREF, LIST and OFFSET to generate a listing, which is used to calculate addresses of functions and data. The code was processed by the binder with MAP to generate a binder map, which is used to calculate the addresses of static and external variables. The program was created with the option TERMTHDACT(UADUMP) which produced both a Language environment dump and a system dump.

Figure 1. C routine with a divide-by-zero error (AMODE 64)
/* C Routine with a Divide-by-Zero Error */
#pragma options(noinline)
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
int statint = 73;
int fa;
int funcb(int *pp);
int main(void) {
  int aa, bb=1;
  aa = bb;
  aa = funcb(&aa);
  return(aa);
}
int funcb(int *pp) {
  int result;
  fa = *pp;
  result = fa/(statint-73);
  printf("Result = %d\n",result);
  return result;
}

To debug this routine, use the following steps:

  1. Locate the Original Condition message in the Condition Information for Active Routines section of the dump. In this example, the message is CEE3209S. The system detected a fixed-point divide exception. This message indicates the error was caused by an attempt to divide by zero. For additional information about CEE3209S, see z/OS Language Environment Runtime Messages.

    The traceback section of the dump indicates that the exception occurred at offset X'52' within function funcb. This information is used along with the compiler-generated Pseudo Assembly Listing to determine where the problem occurred.

    If the GONUMBER compiler option is specified, statement number information is in the dump. Figure 2 shows the generated traceback from the dump.

    Figure 2. Sections of the dump from example C/C++ routine (AMODE 64) (Part 1 of 2)
    CEE3DMP V1 R8.0: Condition processing resulted in the unhandled condition.         Tue Feb 21 16:50:50 2006             Page:    1
    
    Information for enclave main
    
      Information for thread 25AC70A000000000
    
      Traceback:
        DSA       Entry       E  Offset  Statement   Load Mod             Program Unit                   Service  Status
        00000001  CEEHDSP     +00000000              CELQLIB              CEEHDSP                        HLE7730  Call
        00000002  CEEOSIGJ    +0000094E              CELQLIB              CEEOSIGJ                       HLE7730  Call
        00000003  CELQHROD    +0000024E              CELQLIB              CELQHROD                       HLE7730  Call
        00000004  CEEOSIGG    -1D58AE60              CELQLIB              CEEOSIGG                       HLE7730  Call
        00000005  CELQHROD    +0000024E              CELQLIB              CELQHROD                       HLE7730  Call
        00000006  funcb       +00000052  18          CDIVZERO             CDIVZERO                                Exception
        00000007  main        +00000026  12          CDIVZERO             CDIVZERO                                Call
        00000008  CELQINIT    +00001340              CELQLIB              CELQINIT                       HLE7730  Call
    
        DSA       DSA Addr          E  Addr             PU Addr           PU Offset   Comp Date Attributes
        00000001  00000001082FAAC0  0000000025793E88    0000000025793E88  00000000    20060109  XPLINK  EBCDIC  POSIX  Floating Point
        00000002  00000001082FD3E0  000000002588FE28    000000002588FE28  0000094E    20051214  XPLINK  EBCDIC  POSIX  Floating Point
        00000003  00000001082FDDE0  00000000257B50D8    00000000257B50D8  0000024E    20051214  XPLINK  EBCDIC  POSIX  Floating Point
        00000004  00000001082FE020  00000000258894E0    00000000258894E0  1D58AE60    20051214  XPLINK  EBCDIC  POSIX  Floating Point
        00000005  00000001082FEE40  00000000257B50D8    00000000257B50D8  0000024E    20051214  XPLINK  EBCDIC  POSIX  Floating Point
        00000006  00000001082FF080  00000000257080D0    0000000000000000  ********    20060221  XPLINK  EBCDIC  POSIX  IEEE
        00000007  00000001082FF180  0000000025708170    0000000000000000  ********    20060221  XPLINK  EBCDIC  POSIX  IEEE
        00000008  00000001082FF280  000000002570B010    000000002570B010  00001340    20051214  XPLINK  EBCDIC  POSIX  Floating Point
    
        Fully Qualified Names
        DSA       Entry       Program Unit                                        Load Module
        00000006  funcb       PLPSC://'POSIX.CRTL.C(CDIVZERO)'                    /u/alfcar/tools/CDIVZERO
        00000007  main        PLPSC://'POSIX.CRTL.C(CDIVZERO)'                    /u/alfcar/tools/CDIVZERO
    
      Condition Information for Active Routines
        Condition Information for PLPSC://'POSIX.CRTL.C(CDIVZERO)' (DSA address 00000001082FF080)
          CIB Address: 00000001082FBE00
          Current Condition:
            CEE0198S The termination of a thread was signaled due to an unhandled condition.
          Original Condition:
            CEE3209S The system detected a fixed-point divide exception (System Completion Code=0C9).
          Location:
            Program Unit: PLPSC://'POSIX.CRTL.C(CDIVZERO)'
            Entry:        funcb Statement: 18 Offset: +00000052
          Machine State:
            ILC..... 0002    Interruption Code..... 0009
            PSW..... 0785240180000000 0000000025708124
            GPR0..... 0000000000000000  GPR1..... 00000001082FFA40  GPR2..... 0000000108414340  GPR3..... 0000000108413430
            GPR4..... 00000001082FF080  GPR5..... 0000000108300060  GPR6..... 0000000000000000  GPR7..... 0000000100000001
            GPR8..... 0000000025700CC8  GPR9..... 00000000257081B8  GPR10.... 0000000025708278  GPR11.... 0000000108414330
            GPR12.... 0000000100005300  GPR13.... 0000000000006F60  GPR14.... 00000000257BF218  GPR15.... 000000000000001F
            FPC...... 00000000
            FPR0..... 4327CCCA  93BCEEF1            FPR1..... 00000000  00000000
            FPR2..... 00000000  00000000            FPR3..... 00000000  00000000
            FPR4..... 3C100000  00000000            FPR5..... 00000000  00000000
            FPR6..... 34100000  00000000            FPR7..... 00000000  00000000
            FPR8..... 00000000  00000000            FPR9..... 00000000  00000000
            FPR10.... 00000000  00000000            FPR11.... 00000000  00000000
            FPR12.... 00000000  00000000            FPR13.... 00000000  00000000
            FPR14.... 00000000  00000000            FPR15.... 00000000  00000000
            Start of changeVR0...... 4327CCCA 93BCEEF1 00000000 00000000        VR1...... 00000000 00000000 00000000 00000000
            VR2...... 00000000 00000000 00000000 00000000        VR3...... 00000000 00000000 00000000 00000000
            VR4...... 3C100000 00000000 00000000 00000000        VR5...... 00000000 00000000 00000000 00000000
            VR6...... 3C100000 00000000 00000000 00000000        VR7...... 00000000 00000000 00000000 00000000
            VR8...... 00000000 00000000 00000000 00000000        VR9...... 00000000 00000000 00000000 00000000
            VR10..... 00000000 00000000 00000000 00000000        VR11..... 00000000 00000000 00000000 00000000
            VR12..... 00000000 00000000 00000000 00000000        VR13..... 00000000 00000000 00000000 00000000
            VR14..... 00000000 00000000 00000000 00000000        VR15..... 00000000 00000000 00000000 00000000
            VR16..... 00000000 00000000 00000000 00000000        VR17..... 00000000 00000000 00000000 00000000
            VR18..... 00000000 00000000 00000000 00000000        VR19..... 00000000 00000000 00000000 00000000
            VR20..... 00000000 00000000 00000000 00000000        VR21..... 00000000 00000000 00000000 00000000
            VR22..... 00000000 00000000 00000000 00000000        VR23..... 00000000 00000000 00000000 00000000
            VR24..... 00000000 00000000 00000000 00000000        VR25..... 00000000 00000000 00000000 00000000
            VR26..... 00000000 00000000 00000000 00000000        VR27..... 00000000 00000000 00000000 00000000
            VR28..... 00000000 00000000 00000000 00000000        VR29..... 00000000 00000000 00000000 00000000
            VR30..... 00000000 00000000 00000000 00000000        VR31..... 00000000 00000000 00000000 00000000End of change    
      Storage dump near condition, beginning at location(0000000025708112)
          +0000 0000000025708112  0004E300 70000014 A70BFFB7 8E600020  |..T.....x....-..|
          +0010 0000000025708122  1D60B904 00075000 48C0E320 48C00014  |.-....&...T.....|
    
      Parameters, Registers, and Variables for Active Routines:
        funcb (DSA address 00000001082FF080):
          DOWNSTACK DSA
          Saved Registers:
            GPR0..... ****************  GPR1..... ****************  GPR2..... ****************  GPR3..... ****************
            GPR4..... 00000001082FF080  GPR5..... BBBBBBBBBBBBBBBB  GPR6..... 00000000257B50D8  GPR7..... 0000000100000001
            GPR8..... 0000000025700CC8  GPR9..... 00000000257081B8  GPR10.... 0000000025708278  GPR11.... 0000000108414330
            GPR12.... 4040404040404040  GPR13.... 4040404040404040  GPR14.... 4040404040404040  GPR15.... 4040404040404040
    Figure 3. Sections of the dump from example C/C++ routine (AMODE 64) (Part 2 of 2)
        GPREG STORAGE:
          Storage around GPR0  is invalid.
          Storage around GPR1  is invalid.
          Storage around GPR2  is invalid.
          Storage around GPR3  is invalid.
          Storage around GPR4 (00000001082FF080)
            +0800 00000001082FF880  00000001 082FF180 00000001 08300060  |......1........-|
            +0810 00000001082FF890  00000000 25708170 00000000 2570819A  |......a.......a.|
            +0820 00000001082FF8A0  00000000 25700CC8 00000000 25709138  |.......H......j.|
            +0830 00000001082FF8B0  00000000 25708278 00000001 08414330  |......b.........|
            +0840 00000001082FF8C0  00000001 00005300 00000000 00006F60  |..............?-|
            +0850 00000001082FF8D0  00000000 257BF218 00000000 0000001F  |.....#2.........|
  2. In the traceback, statement number 12, corresponding to DSA 7, refers to line: aa = funcb(&aa); in the listing. This is were entry funcb is called. Similarly, statement number 18, corresponding to DSA 6, points to line: result = fa/(statint-73); in the listing. This line is where the divide by zero exception takes place.
  3. Locate the instruction with the divide-by-zero error in the Pseudo Assembly Listing in Figure 4.

    The offset (within funcb) of the exception from the traceback (X'52') reveals the divide instruction: DR R6,R0 at that location. Instructions at offsets X'32' through X'58' refer to the result = fa/(statint-73); line of the C/C++ routine.

    Figure 4. Pseudo assembly listing (AMODE 64) (Part 1 of 3)
     OFFSET OBJECT CODE        LINE#  FILE#    P S E U D O   A S S E M B L Y   L I S T I N G
    
                               Timestamp and Version Information
     000010  F2F0  F0F6                                       =C'2006'           Compiled Year
     000014  F0F2  F2F1                                       =C'0221'           Compiled Date MMDD
     000018  F1F5  F3F3  F1F5                                 =C'153315'         Compiled Time HHMMSS
     00001E  F0F1  F0F8  F0F0                                 =C'010800'         Compiler Version
                               Timestamp and Version End
    
    15694A01 V1.8 z/OS XL C                             'POSIX.CRTL.C(CDIVZERO)': funcb               02/21/06 15:33:15   Page   148
    
     OFFSET OBJECT CODE        LINE#  FILE#    P S E U D O   A S S E M B L Y   L I S T I N G
    
                               000015 |       *  int funcb(int *pp) {
    
     000028                                    @2L0     DS    0D
     000028  00C300C5                                         =F'12779717'       XPLink entrypoint marker
     00002C  00C500F1                                         =F'12910833'
     000030  00000108                                         =F'264'
     000034  00000100                                         =F'256'
     000000                    000015 |        funcb    DS    0D
     000000  EB59  4708  0024  000015 |                 STMG  r5,r9,1800(r4)
     000006  A74B  FF00        000015 |                 AGHI  r4,H'-256'
     00000A                    End of Prolog
    
     00000A  C090  0000  006F  000000 |                 LARL  r9,F'111'
     000010  E310  4980  0024  000015 |                 STG   r1,pp(,r4,2432)
                               000016 |       *    int result;
                               000017 |       *    fa = *pp;
     000016  E360  4980  0004  000017 |                 LG    r6,pp(,r4,2432)
     00001C  E300  6000  0014  000017 |                 LGF   r0,(*)int(,r6,0)
     000022  E360  4808  0004  000017 |                 LG    r6,#Save_ADA_Ptr_2(,r4,2056)
     000028  E360  6000  0004  000017 |                 LG    r6,=A(fa)(,r6,0)
     00002E  5000  6000        000017 |                 ST    r0,fa(,r6,0)
                               000018 |       *    result = fa/(statint-73);
     000032  E360  6000  0014  000018 |                 LGF   r6,fa(,r6,0)
     000038  E370  4808  0004  000018 |                 LG    r7,#Save_ADA_Ptr_2(,r4,2056)
     00003E  E370  7008  0004  000018 |                 LG    r7,=A(statint)(,r7,8)
     000044  E300  7000  0014  000018 |                 LGF   r0,statint(,r7,0)
     00004A  A70B  FFB7        000018 |                 AGHI  r0,H'-73'
     00004E  8E60  0020        000018 |                 SRDA  r6,32
     000052  1D60              000018 |                 DR    r6,r0
     000054  B904  0007        000018 |                 LGR   r0,r7
     000058  5000  48C0        000018 |                 ST    r0,result(,r4,2240)
                               000019 |       *    printf("Result = %d\n",result);
     00005C  E320  48C0  0014  000019 |                 LGF   r2,result(,r4,2240)
     000062  E360  4808  0004  000019 |                 LG    r6,#Save_ADA_Ptr_2(,r4,2056)
     000068  EB56  6010  0004  000019 |                 LMG   r5,r6,=A(printf)(r6,16)
     00006E  B904  0019        000019 |                 LGR   r1,r9
     000072  0D76              000019 |                 BASR  r7,r6
     000074  0700              000019 |                 NOPR  0
                               000020 |       *    return result;
     000076  E330  48C0  0014  000020 |                 LGF   r3,result(,r4,2240)
                               000021 |       *  }
     00007C                    000021 |        @2L3     DS    0H
    
     00007C                    Start of Epilog
     00007C  E370  4818  0004  000021 |                 LG    r7,2072(,r4)
     000082  EB89  4820  0004  000021 |                 LMG   r8,r9,2080(r4)
     000088  4140  4100        000021 |                 LA    r4,256(,r4)
     00008C  47F0  7002        000021 |                 B     2(,r7)
    Figure 5. Pseudo assembly listing (AMODE 64) (Part 2 of 3)
                               ***   General purpose registers used: 1111011101000000
                               ***   Floating point  registers used: 1111111100000000
                               ***   Size of register spill area: 128(max) 0(used)
                               ***   Size of dynamic storage: 0
                               ***   Size of executable code: 144
    
    
                               000001 |       *  /* C Routine with a Divide-by-Zero Error from LE Debugging Guide */
                               000002 |       *  #pragma options(noinline)
                               000003 |       *  #include <stdio.h>
                               000004 |       *  #include <stdlib.h>
                               000005 |       *  #include <errno.h>
                               000006 |       *  int statint = 73;
                               000007 |       *  int fa;
                               000008 |       *  int funcb(int *pp);
                               000009 |       *  int main(void) {
    
     0000C8                                    @1L0     DS    0D
     0000C8  00C300C5                                         =F'12779717'       XPLink entrypoint marker
     0000CC  00C500F1                                         =F'12910833'
     0000D0  00000090                                         =F'144'
     0000D4  00000100                                         =F'256'
     000000                    000009 |        main     DS    0D
     000000  EB57  4708  0024  000009 |                 STMG  r5,r7,1800(r4)
     000006  A74B  FF00        000009 |                 AGHI  r4,H'-256'
     00000A                    End of Prolog
    
                               000010 |       *    int aa, bb=1;
     00000A  A709  0001        000010 |                 LGHI  r0,H'1'
     00000E  5000  48C4        000010 |                 ST    r0,bb(,r4,2244)
                               000011 |       *    aa = bb;
     000012  E300  48C4  0014  000011 |                 LGF   r0,bb(,r4,2244)
     000018  5000  48C0        000011 |                 ST    r0,aa(,r4,2240)
                               000012 |       *    aa = funcb(á);
     00001C  4110  48C0        000012 |                 LA    r1,aa(,r4,2240)
     000020  E350  4808  0004  000012 |                 LG    r5,#Save_ADA_Ptr_1(,r4,2056)
     000026  A775  FF9D        000012 |                 BRAS  r7,funcb
     00002A  0701              000012 |                 NOPR  1
     00002C  B904  0003        000012 |                 LGR   r0,r3
     000030  5000  48C0        000012 |                 ST    r0,aa(,r4,2240)
                               000013 |       *    return(aa);
     000034  E330  48C0  0014  000013 |                 LGF   r3,aa(,r4,2240)
                               000014 |       *  }
     00003A                    000014 |        @1L2     DS    0H
    
     00003A                    Start of Epilog
     00003A  E370  4818  0004  000014 |                 LG    r7,2072(,r4)
     000040  4140  4100        000014 |                 LA    r4,256(,r4)
     000044  47F0  7002        000014 |                 B     2(,r7)
    
                               ***   General purpose registers used: 1111011100000000
                               ***   Floating point  registers used: 1111111100000000
                               ***   Size of register spill area: 128(max) 0(used)
                               ***   Size of dynamic storage: 0
                               ***   Size of executable code: 72
    
                               Constant Area
     000000  D985A2A4 93A3407E 406C8415 00          |Result = %d..   |
    
    
                               PPA1: Entry Point Constants
     000000  02                                               =AL1(2)            Version
     000001  CE                                               =AL1(206)          CEL signature
     000002  07C0                                             =H'1984'           GPR save mask
     000004  00000090                                         =A(PPA2-PPA1)
     000008  80800281                                         =F'-2139094399'    Flags
     00000C  0002                                             =H'2'              Parm length/4
     00000E  0503                                             =H'1283'           Prol len/2; alloca reg; R4 change offset/2
     000010  00000090                                         =F'144'            Code length
     000014  01000000                                         =F'16777216'       Interface mapping flags
     000018  0005  ****                                       AL2(5),C'funcb'
     000020  FFFFFEF8                                         =F'-264'           Offset to Entry Point Marker
                               PPA1 End
    Figure 6. Pseudo assembly listing (AMODE 64) (Part 3 of 3)
                               PPA1: Entry Point Constants
     000000  02                                               =AL1(2)            Version
     000001  CE                                               =AL1(206)          CEL signature
     000002  0700                                             =H'1792'           GPR save mask
     000004  00000068                                         =A(PPA2-PPA1)
     000008  80800281                                         =F'-2139094399'    Flags
     00000C  0000                                             =H'0'              Parm length/4
     00000E  0503                                             =H'1283'           Prol len/2; alloca reg; R4 change offset/2
     000010  00000048                                         =F'72'             Code length
     000014  01000000                                         =F'16777216'       Interface mapping flags
     000018  0004  ****                                       AL2(4),C'main'
     000020  FFFFFF70                                         =F'-144'           Offset to Entry Point Marker
                               PPA1 End
    
    
                               PPA4: Compile Unit Debug Block
     000000  80000000                                         =F'-2147483648'    Additional Flags
     000004  84060238                                         =F'-2079981000'    Flags
     000008  0000000000000000                                 =D'0'              R/O static Offset
     000010  0000000000000000                                 =D'0'              R/W static Offset
     000018  0000000000000000                                 =D'0'              Symbol Offset Table Offset
     000020  FFFFFFFFFFFFFE80                                 =D'-384'           CSECT Start Offset
     000028  0000000000000000                                 =D'0'              Code CSECT Size
     000030  FFFFFFFFFFFFFE88                                 =D'-376'           No program region
     000038  00000000                                         =F'0'              DWARF File Name
     00003C  ****                                             C''
                               PPA4 End
    
                               PPA2: Compile Unit Block
     000000  0300  2204                                       =F'50340356'       Flags
     000004  FFFF  FE40                                       =A(CELQSTRT-PPA2)
     000008  FFFF  FFC0                                       =A(PPA4-PPA2)
     00000C  FFFF  FE50                                       =A(TIMESTMP-PPA2)
     000010  0000  0000                                       =F'0'              No primary
     000014  9140  0000                                       =F'-1858076672'    Flags
                               PPA2 End
  4. Verify the value of the divisor statint. The procedure specified below is to be used for determining the value of static variables only. If the divisor is an automatic variable, there is a different procedure for finding the value of the variable.

    Because this routine was compiled with the RENT option, find the WSA address in the Enclave Control Blocks section of the dump. In this example, this address is X'108300050'. Figure 7 shows the WSA address.

    Figure 7. C/C++ CAA information in dump (AMODE 64)
      Enclave Control Blocks:
        .
        .
        .
        DLL Information:
        WSA Addr          Module Addr          Thread ID         Use Count  Name
        0000000108300050                                         00000001   main
  5. Routines compiled with the RENT option must also be processed by the binder. The binder produces the Writable Static Map. Find the offset of statint in the Writable Static Map in Figure 8. In this example, the offset is X'30'.
    Figure 8. Writable static map (AMODE 64)
     ---------------
     CLASS  C_WSA64           LENGTH =       38  ATTRIBUTES = MRG, DEFER , RMODE= 64
                              OFFSET =        0 IN SEGMENT 002       ALIGN = QDWORD
     ---------------
    
                 CLASS
                OFFSET  NAME                TYPE    LENGTH   SECTION
                     0  $PRIV000012      PART            10
                    10  CDIVZERO#S       PART            20  CDIVZERO#C
                    30  statint          PART             4  statint
                    34  fa               PART             4  fa
  6. Add the WSA address of X'108300050' to the offset of statint. The result is X'108300080'. This is the address of the variable statint, which is in the writable static area.
  7. Use IPCS to display the writeable static area in the system dump. The value at location X'108300080' is X'49' (that is, statint is 73), and hence the fixed-point divide exception.
    Figure 9. IPCS storage display of the writeable static area (AMODE 64)
    LIST 0000000108300050 LEN(X'00000100')
    
    LIST 01_08300050. ASID(X'0015') LENGTH(X'0100') AREA
    _8300050. C36DE6E2 C1F6F440 40404040 40404040 |C_WSA64         |
    _8300060. 00000001 08300084 00000001 08300080 |.......d........|
    _8300070. 00000000 000000C0 00000000 2548D200 |.......{......K.|
    _8300080. 00000049 00000001 00000000 00000000 |................|
    _8300090 LENGTH(X'10')==>All bytes contain X'00'
    _83000A0. 00000001 08300000 00000000 00000220 |................|
    _83000B0. 00000001 083002D0 00000001 083004B8 |.......}........|
    _83000C0. 00000001 083004F5 00000001 08300532 |.......5........|
    _83000D0. 00000001 0830056F 00000001 083005AC |.......?........|
    _83000E0. 00000001 083005E9 00000001 08300626 |.......Z........|
    _83000F0. 00000001 08300663 00000001 08300A70 |................|
    _8300100. 00000001 08300AAD 00000000 00000000 |................|
    _8300110 LENGTH(X'40')==>All bytes contain X'00'