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 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.

Figure 1. C routine with a divide-by-zero error
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
int statint = 73;
int fa;
void funcb(int *pp);

int main(void) {
  int aa, bb=1;
  aa = bb;
  funcb(&aa);
  return(99);
}

void funcb(int *pp) {
  int result;
  fa = *pp;
  result = fa/(statint-73);
  return;
}

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 more information about CEE3209S, see z/OS Language Environment Runtime Messages.

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

    If the TEST compiler option is specified, variable information is in the dump. 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 (divide-by-zero error)
    CEE3DMP V1 R12.0: Condition processing resulted in the unhandled condition.         05/24/10 6:20:36 PM                  Page:    1  
    ASID: 0049   Job ID: JOB23480   Job name: CDIVZERO   Step name: STEP1      UserID: HEALY                                            
                                                                                                                                        
    CEE3845I CEEDUMP Processing started.                                                                                                
                                                                                                                                        
    Information for enclave main                                                                                                        
                                                                                                                                        
      Information for thread 8000000000000000                                                                                           
                                                                                                                                        
      Traceback:                                                                                                                        
        DSA   Entry       E  Offset  Statement   Load Mod             Program Unit                   Service  Status                    
        1     CEEHDSP     +00004030              CEEPLPKA             CEEHDSP                        D1908    Call                      
        2     funcb       +00000076  18          CDIVZERO                                                     Exception                 
        3     main        +00000064  12          CDIVZERO                                                     Call                      
        4     EDCZMINV    +000000C2              CEEEV003                                                     Call                      
        5     CEEBBEXT    +000001B6              CEEPLPKA             CEEBBEXT                       D1908    Call                      
                                                                                                                                        
        DSA   DSA Addr   E  Addr    PU Addr    PU Offset  Comp Date  Compile Attributes                                                 
        1     20FCB358   209C4238   209C4238   +00004030  20061215   CEL                                                                
        2     20FCB2B0   20900960   20900960   +00000076  20070115   C/C++                                                              
        3     20FCB208   209008E0   209008E0   +00000064  20070115   C/C++                                                              
        4     20FCB0F0   20E699EE   20E699EE   +000000C2  20061215   LIBRARY                                                            
        5     20FCB030   20992208   20992208   +000001B6  20061215   CEL                                                                
    
    Condition Information for Active Routines
          Condition Information for  (DSA address 20FCB2B0)
            CIB Address: 20FCBC78
            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:  Entry: funcb Statement: 18 Offset: +00000076
            Machine State:
              ILC..... 0002    Interruption Code..... 0009
              PSW..... 078D2400 A09009D8
              GPR0..... 00000000_20900A08  GPR1..... 00000000_00000000  GPR2..... 00000000_20FCB2A8  GPR3..... 00000000_2090099A
              GPR4..... 00000000_00000000  GPR5..... 00000000_00000001  GPR6..... 00000000_20900B24  GPR7..... 00000000_20900098
              GPR8..... 00000000_00000030  GPR9..... 00000000_80000000  GPR10.... 00000000_A0E699E2  GPR11.... 00000000_A0992208
              GPR12.... 00000000_209139B0  GPR13.... 00000000_20FCB2B0  GPR14.... 00000000_20914F50  GPR15.... 00000000_00000008
          Storage dump near condition, beginning at location: 209009C6
            +000000 209009C6  5811E000 504FE000 A71AFFB7 8E400020  1D4158F0 306A4110 D0985000 D0985050  |....&|..x.... .....0.....q&..q&&|
          GPREG STORAGE:
            Storage around GPR0 (20900A08)
              -0020 209009E8  0DEF18F5 58D0D004 58E0D00C 9825D01C  051E0707 00000000 00000008 209000B8  |...5........q...................|
              +0000 20900A08  D985A2A4 93A3407E 406C8415 00000000  1CCEA106 00000228 00000178 00000000  |Result = %d.....................|
    
    ⋮
  2. Locate the instruction with the divide-by-zero error in the Pseudo Assembly Listing in Figure 3.

    The offset (within funcb) of the exception from the traceback (X'76') reveals the divide instruction: DR r4,r1 at that location. Instructions X'66' through X'76' refer to the result = fa/(statint-73); line of the C/C++ routine.

    Figure 3. Pseudo assembly listing (C/C++ routine divide-by-zero error)
    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) {                                                                    
    000000                    000015 |        funcb    DS       0D                                                                      
    .                                                                                                                                   
    .                                                                                                                                   
    .                                                                                                                                   
    000046  50D0  E004        000015 |                 ST       r13,4(,r14)                                                             
    00004A  18DE              000015 |                 LR       r13,r14                                                                 
    00004C                    End of Prolog                                                                                             
                                                                                                                                        
    00004C  58E0  C1F4        000000 |                 L        r14,_CEECAA_(,r12,500)                                                  
                              000016 |       *    int result;                                                                           
                              000017 |       *    fa = *pp;                                                                             
    000050  5820  1000        000017 |                 L        r2,pp(,r1,0)                                                            
    000054  5810  3062        000018 |                 L        r1,=Q(statint)(,r3,98)                                                  
    000058  58F0  3066        000017 |                 L        r15,=Q(fa)(,r3,102)                                                     
    00005C  C000  0000  0026  000000 |                 LARL     r0,F'38'                                                                
    000062  5840  2000        000017 |                 L        r4,(*)int(,r2,0)                                                        
                              000018 |       *    result = fa/(statint-73);                                                             
    000066  5811  E000        000018 |                 L        r1,statint(r1,r14,0)                                                    
    00006A  504F  E000        000017 |                 ST       r4,fa(r15,r14,0)                                                        
    00006E  A71A  FFB7        000018 |                 AHI      r1,H'-73'                                                               
    000072  8E40  0020        000018 |                 SRDA     r4,32                                                                   
    000076  1D41              000018 |                 DR       r4,r1                                                                   
                              000019 |       *    printf("Result = %d\n",result);                                                       
    000078  58F0  306A        000019 |                 L        r15,=V(printf)(,r3,106)                                                 
    00007C  4110  D098        000019 |                 LA       r1,#MX_TEMP2(,r13,152)                                                  
    000080  5000  D098        000019 |                 ST       r0,#MX_TEMP2(,r13,152)                                                  
    000084  5050  D09C        000019 |                 ST       r5,#MX_TEMP2(,r13,156)                                                  
    000088  0DEF              000019 |                 BASR     r14,r15                                                                 
                              000020 |       *    return result;                                                                        
    00008A  18F5              000020 |                 LR       r15,r5                                                                  
                              000021 |       *  }                                                                                       
    00008C                    000021 |        @2L3     DS       0H                                                                      
                                                                                                                                        
    00008C                    Start of Epilog                                                                                           
    00008C  58D0  D004        000021 |                 L        r13,4(,r13)                                                             
    000090  58E0  D00C        000021 |                 L        r14,12(,r13)                                                            
    000094  9825  D01C        000021 |                 LM       r2,r5,28(r13)                                                           
    000098  051E              000021 |                 BALR     r1,r14                                                                  
    00009A  0707              000021 |                 NOPR     7                                                                       
                                                                                                                                        
    00009C                    Start of Literals                                                                                         
    00009C  00000000                                            =Q(statint)                                                             
    0000A0  00000000                                            =Q(fa)                                                                  
    0000A4  00000000                                            =V(printf)                                                              
    0000A8                    End of Literals                                                                                           
                                                                                                                                        
                              ***   General purpose registers used: 1111110000001111                                                    
                              ***   Floating point  registers used: 1111111100000000                                                    
                              ***   Size of register spill area: 128(max) 0(used)                                                       
                              ***   Size of dynamic storage: 168                                                                        
                              ***   Size of executable code: 156                                                                        
                                                                                                                                        
                              Constant Area                                                                                             
    000000  D985A2A4 93A3407E 406C8415 00          |Result = %d..   |                                                                   
                                                                                                                                        
                              PPA1: Entry Point Constants                                                                               
    000000  1CCEA106                                            =F'483303686'      Flags                                                
    000004  00000228                                            =A(PPA2-main)                                                           
    000008  00000178                                            =A(PPA3-main)                                                           
    00000C  00000000                                            =F'0'              No EPD                                               
    000010  FE000000                                            =F'-33554432'      Register save mask                                   
    000014  00000000                                            =F'0'              Member flags                                         
    000018  90                                                  =AL1(144)          Flags                                                
    000019  000000                                              =AL3(0)            Callee's DSA use/8                                   
    00001C  0040                                                =H'64'             Flags                                                
    00001E  0012                                                =H'18'             Offset/2 to CDL                                      
    000020  00000000                                            =F'0'              Reserved                                             
    000024  5000003C                                            =F'1342177340'     CDL function length/2                                
    000028  FFFFFEC8                                            =F'-312'           CDL function EP offset                               
    00002C  38260000                                            =F'942014464'      CDL prolog                                           
    000030  40090033                                            =F'1074331699'     CDL epilog                                           
    000034  00000000                                            =F'0'              CDL end                                              
    000038  0004  ****                                          AL2(4),C'main'                                                          
                              PPA1 End                                                                                                  
    ⋮                                                                                                                                   
  3. 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. For more information about finding automatic variables in a dump, see Steps for finding automatic variables .

    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'20914F50'. Figure 4 shows the WSA address.

    Figure 4. C/C++ CAA information in dump (C/C++ routine divide-by-zero error)
      Enclave Control Blocks:                                                                                                           
    ⋮                                                                                                                                  
        WSA address.................20914F50                                                                                  
    ⋮                                                                                                                                   
  4. 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 5. In this example, the offset is X'0'.
    Figure 5. Writable static map (C/C++ routine divide-by-zero error)
    ⋮                                                                                                                                  
    ---------------                                                                                                                     
    CLASS  C_WSA             LENGTH =       AC  ATTRIBUTES = MRG, DEFER , RMODE=ANY                                                     
                             OFFSET =        0 IN SEGMENT 002       ALIGN = DBLWORD                                                     
    ---------------                                                                                                                     
                                                                                                                                        
                CLASS                                                                                                                   
               OFFSET  NAME                TYPE    LENGTH   SECTION                                                                     
                    0  statint          PART             4  statint                                                                     
                    8  fa               PART             4  fa                                                                          
                   10  environ          PART             4  environ                                                                     
                   18  errno            PART             4  errno                                                                       
    ⋮ 
  5. Add the WSA address of X'20914F50' to the offset of statint. The result is X'20914F50'. This is the address of the variable statint, which is in the writable static area.

    The writable static area is shown in the Enclave Storage section of the dump. For a load module, the writable static area is storage allocated by the C/C++ runtime for the C/C++ user, so it is in the user heap. For a program object, the writable static area is storage allocated by the loader and is shown in the WSA for Program Object(s) section of the dump.

    For this example, the program was built as a program object. The writable static area is displayed in the Enclave Storage section of the dump, shown in Figure 6.

  6. To find the variable statint in the writable static area, locate the closest address listed that is before the address of statint. In this case, that address is X'20914F50'. Count across X'00' to location X'20914F50'. The value at that location is X'49' (that is, statint is 73), and hence the fixed point divide exception.
Figure 6. Enclave storage section of dump (C/C++ routine divide-by-zero error)
  Enclave Storage:                                                                                                                  
⋮                                                                                                                                
    WSA for Program Object(s)                                                                                                       
    WSA: 20914F50                                                                                                                   
      +000000 20914F50  00000049 00000000 00000001 00000000  2090A880 00000000 00000000 00000000  |..................y.............|
      +000020 20914F70  20910260 2091026A 00000000 00000000  00000000 00000000 00000000 00000000  |.j.-.j..........................|
      +000040 20914F90  00000001 00000000 00000001 00000000  00000000 00000000 00000000 00000000  |................................|
      +000060 20914FB0  00000000 00000000 00000000 00000000  00000000 00000000 00000000 00000000  |................................|
      +000080 20914FD0  00000000 00000000 00000000 00000000  2090F6BC 00000000 2090F28C 00000000  |..................6.......2.....|
      +0000A0 20914FF0  2090F4A4 00000000 00000000 00000000  00000000 00000000 00000000 00000000  |..4u............................|
⋮