Calling a nonexistent XPLINK function

Figure 1 demonstrates the error of calling a nonexistent function. This routine was compiled with the compiler options XPLINK, LIST and RENT and was run with the option TERMTHDACT(DUMP). This routine was not compiled with the TEST(ALL) compile option. As a result, arguments and variables do not appear in the dump.

Figure 1. C/C++example of calling a nonexistent XPLINK function
 #include <stdio.h>
 #include <stdlib.h>
 #include <errno.h>
 #include <signal.h>
 void funca(int* aa);
 int (*func_ptr)(void)=0;
 int main(void) {
   int aa;
   funca(&aa);
   printf("result of funca = %d\n",aa);
   return;
 }
 void funca(int* aa) {
   *aa = func_ptr();
   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, shown in Sections of the dump from example C routine (calling a nonexistent XPLINK function). In this example, the message is CEE3201S The system detected an operation exception (System Completion Code=0C1). This message suggests that the error was caused by an attempt to branch to an unknown address. For additional information about CEE3201S, see z/OS Language Environment Runtime Messages.

    The location section of the dump indicates that the exception occurred at offset X'-20900158' within function funca and that there may have been a bad branch from offset X'+0000001C'. The negative offset indicates that the offset cannot be used to locate the instruction that caused the error. Another indication of bad data is the value of X'80000004' in the instruction address of the PSW. This address indicates that an instruction in the routine branched outside the bounds of the routine.

  2. Find the branch instruction at offset X'+0000001C' of funca in the listing in Figure 2. This instruction is BASR r7,r6. This branch is part of the source statement *aa = func_ptr().
    Figure 2. Pseudo assembly listing (calling a nonexistent XPLINK function)
                               00015 │       *  void funca(int* aa) {
    ⋮
     000020                                   @2L0     DS    0D
     000020  00C300C5                                        =F'12779717'       XPLink entrypoint marker
     000024  00C500F1                                        =F'12910833'
     000028  FFFFFFE0                                        =F'-32'
     00002C  00000080                                        =F'128'
     000000                    00015 │        funca    DS    0D
     000000  9057  4784        00015 │                 STM   r5,r7,1924(r4)
     000004  A74A  FF80        00015 │                 AHI   r4,H'-128'
     000008                    End of Prolog
    
     000008  5010  48C0        00015 │                 ST    r1,aa(,r4,2240)
                               00016 │       *    *aa = func_ptr();
     00000C  5860  4804        00016 │                 L     r6,#Save_ADA_Ptr_2(,r4,2052)
     000010  5860  6018        00016 │                 L     r6,=A(func_ptr)(,r6,24)
     000014  5860  6000        00016 │                 L     r6,func_ptr(,r6,0)
     000018  9856  6010        00016 │                 LM    r5,r6,&ADA_&EPA(r6,16)
     00001C  0D76              00016 │                 BASR  r7,r6
     00001E  4700  0004        00016 │                 NOP   4
     000022  1803              00016 │                 LR    r0,r3
     000024  5860  48C0        00016 │                 L     r6,aa(,r4,2240)
     000028  5000  6000        00016 │                 ST    r0,(*)int(,r6,0)
                               00017 │       *    return;
                               00018 │       *  }
     00002C                    00018 │        @2L3     DS    0H
    
     00002C                    Start of Epilog
     00002C  5870  480C        00018 │                 L     r7,2060(,r4)
     000030  4140  4080        00018 │                 LA    r4,128(,r4)
     000034  07F7              00018 │                 BR    r7
    ⋮
  3. Find the offset of func_ptr in the Writable Static Map, shown in Figure 3.
    Figure 3. Writable static map (calling a nonexistent XPLINK function)
    ⋮
    ---------------
    CLASS  C_WSA             LENGTH =       3C  ATTRIBUTES = MRG, DEFER , RMODE=ANY
                             OFFSET =        0 IN SEGMENT 002       ALIGN = DBLWORD
    ---------------
    
                CLASS
               OFFSET  NAME                TYPE    LENGTH   SECTION
    
                    0  $PRIV000011      PART            10
                   10  exist            PART            28  EXIST
                   38  func_ptr         PART             4  func_ptr
  4. Add the offset of func_ptr (X'38') to the address of WSA (X'20914FC0'). The result ( X'20914FF8') is the address of the function pointer func_ptr in the writable static storage area within the heap. This value is 0, indicating the variable is uninitialized. Figure 4 shows the sections of the dump.
    Figure 4. Enclave control blocks and storage sections in dump (calling a nonexistent XPLINK function)
      Enclave Control Blocks:                                                                                                           
    ⋮                                                                                                                                  
        DLL Information:                                                                                                                
        WSA Addr  Module Addr  Thread ID         Use Count  Name                                                                        
        20914FC0                                 00000001   main                                                                        
                                                                                                                                        
        WSA address.................20914FC0                                                                       
                                                                                                                                        
      Enclave Storage:                                                                                                                  
    ⋮                                                                                                                                   
        WSA for Program Object(s)                                                                                                       
        WSA: 20914FC0                                                                                          
          +000000 20914FC0  C36DE6E2 C1404040 40404040 40404040  9985A2A4 93A34096 864086A4 95838140  |C_WSA           result of funca |
          +000020 20914FE0  7E406C84 15000000 20914FF8 00000000  00000060 20F23280 00000000 00000000  |= %d.....j|8.......-.2..........|
    ⋮