Calling a nonexistent non-XPLINK function
Figure 1 demonstrates the error of calling a nonexistent function. This routine was compiled with the compiler options LIST, OFFSET, and RENT and was run with the option TERMTHDACT(DUMP). 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. This routine was not compiled with the TEST(ALL) compiler option. As a result, arguments and variables do not appear in the dump.
#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:
- Locate the Original Condition message in the Condition Information for Active Routines section
of the dump, shown in Figure 2. In this example, the message is
CEE3201S The system detected an operation exception (System Completion Code=0C1).
It suggests that the error was caused by an attempt to branch to an unknown address. For more information about CEE3201S, see Language Environment runtime messages in z/OS Language Environment Runtime Messages.The Location section of the dump indicates that the exception occurred at offset X'-20900978' within function
funcaand that there may have been a bad branch from offset X'+0000005A' within functionfunca. 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'80000002' in the instruction address of the PSW. This address indicates that an instruction in the routine branched outside the bounds of the routine.Figure 2. Sections of the dump from example C routine (calling a nonexistent subroutine) CEE3DMP V1 R12.0: Condition processing resulted in the unhandled condition. 04/18/10 5:38:23 PM Page: 1 ASID: 0049 Job ID: JOB21060 Job name: EXIST 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 funca -20900978 EXIST Exception 3 main +0000005C EXIST 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 20FCB350 209D2B08 209D2B08 +00004030 20061215 CEL 2 20FCB2B0 20900978 20900978 -20900978 20070115 C/C++ 3 20FCB208 209008E0 209008E0 +0000005C 20070115 C/C++ 4 20FCB0F0 20E699EE 20E699EE +000000C2 20061215 LIBRARY 5 20FCB030 209A0AD8 209A0AD8 +000001B6 20061215 CEL Condition Information for Active Routines Condition Information for (DSA address 20FCB2B0) CIB Address: 20FCBC70 Current Condition: CEE0198S The termination of a thread was signaled due to an unhandled condition. Original Condition: CEE3201S The system detected an operation exception (System Completion Code=0C1). Location: Program Unit: Entry: funca Statement: Offset: -20900978 Possible Bad Branch: Statement: Offset: +0000005A Machine State: ILC..... 0002 Interruption Code..... 0001 PSW..... 078D1400 80000002 GPR0..... 00000000_20FCB350 GPR1..... 00000000_20FCB2A0 GPR2..... 00000000_20FCB2A0 GPR3..... 00000000_209009B2 GPR4..... 00000000_A09A0BBC GPR5..... 00000000_20912648 GPR6..... 00000000_20900AA4 GPR7..... 00000000_20900098 GPR8..... 00000000_00000030 GPR9..... 00000000_80000000 GPR10.... 00000000_A0E699E2 GPR11.... 00000000_A09A0AD8 GPR12.... 00000000_209139B0 GPR13.... 00000000_20FCB2B0 GPR14.... 00000000_A09009D4 GPR15.... 00000000_00000000 Storage dump near condition, beginning at location: 00000000 +000000 00000000 Inaccessible storage. GPREG STORAGE: Storage around GPR0 (20FCB350) -0020 20FCB330 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 |................................| +0000 20FCB350 0808CEE1 20FCB2B0 20FCE470 A09D6B3A A09EFFD8 20FCB350 20FCB7A8 20912648 |..........U...,....Q...&...y.j..| ⋮ Parameters, Registers, and Variables for Active Routines: CEEHDSP (DSA address 20FCB350): UPSTACK DSA Saved Registers: GPR0..... 20FCB350 GPR1..... 20FCB7A8 GPR2..... 20912648 GPR3..... 00000080 GPR4..... 209D7734 GPR5..... A0915000 GPR6..... 2090C2A8 GPR7..... 20FCBC70 GPR8..... A09D665A GPR9..... 20FCD34E GPR10.... 20FCC34F GPR11.... 209D2B08 GPR12.... 209139B0 GPR13.... 20FCB350 GPR14.... A09D6B3A GPR15.... A09EFFD8 ⋮ funca (DSA address 20FCB2B0): UPSTACK DSA Saved Registers: GPR0..... 20FCB350 GPR1..... 20FCB2A0 GPR2..... 20FCB2A0 GPR3..... 209009B2 GPR4..... A09A0BBC GPR5..... 20912648 GPR6..... 20900AA4 GPR7..... 20900098 GPR8..... 00000030 GPR9..... 80000000 GPR10.... A0E699E2 GPR11.... A09A0AD8 GPR12.... 209139B0 GPR13.... 20FCB2B0 GPR14.... A09009D4 GPR15.... 00000000 ⋮ - Find the branch instructions at offset X'+0000005A' of
funcain the listing in Figure 3. The instruction isBASR r14,r15. This branch is part of the source statement*aa = func_ptr().Figure 3. Pseudo assembly listing (calling a nonexistent subroutine) 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 000016 | * void funca(int* aa) { 000000 000016 | funca DS 0D . . . 000046 50D0 E004 000016 | ST r13,4(,r14) 00004A 18DE 000016 | LR r13,r14 00004C End of Prolog 00004C 58E0 C1F4 000000 | L r14,_CEECAA_(,r12,500) 000017 | * *aa = func_ptr(); 000050 58F0 303A 000017 | L r15,=Q(func_ptr)(,r3,58) 000054 1821 000016 | LR r2,r1 000056 58FF E000 000017 | L r15,func_ptr(r15,r14,0) 00005A 0DEF 000017 | BASR r14,r15 00005C 5810 2000 000017 | L r1,aa(,r2,0) 000060 50F0 1000 000017 | ST r15,(*)int(,r1,0) 000018 | * return; 000019 | * } 000064 000019 | @2L3 DS 0H 000064 Start of Epilog 000064 58D0 D004 000019 | L r13,4(,r13) 000068 58E0 D00C 000019 | L r14,12(,r13) 00006C 9824 D01C 000019 | LM r2,r4,28(r13) 000070 051E 000019 | BALR r1,r14 000072 0707 000019 | NOPR 7 - Find the offset of
func_ptrin the Writable Static Map, shown in Figure 4, as produced by the binder.Figure 4. Writable static map (calling a nonexistent subroutine) ⋮ --------------- CLASS C_WSA LENGTH = A4 ATTRIBUTES = MRG, DEFER , RMODE=ANY OFFSET = 0 IN SEGMENT 002 ALIGN = DBLWORD --------------- CLASS OFFSET NAME TYPE LENGTH SECTION 0 func_ptr PART 4 func_ptr 8 environ PART 4 environ 10 errno PART 4 errno 18 tzname PART 8 tzname ⋮ - Add the offset of
FUNC@PTR(X'0') to the address of WSA (X'20914F58'). The result ( X'20914F58') is the address of the function pointerfunc_ptrin the writable static storage area within the heap. This value is 0, indicating the variable is uninitialized. Figure 5 shows the sections of the dump.Figure 5. Enclave control blocks and storage sections in dump (calling a nonexistent subroutine) ⋮ Enclave Control Blocks: ⋮ WSA address.................20914F58 Enclave Storage: ⋮ WSA for Program Object(s) WSA: 20914F58 +000000 20914F58 00000000 00000000 2090A880 00000000 00000000 00000000 20910260 2091026A |..........y..............j.-.j..| +000020 20914F78 00000000 00000000 00000000 00000000 00000000 00000000 00000001 00000000 |................................| +000040 20914F98 00000001 00000000 00000000 00000000 00000000 00000000 00000000 00000000 |................................| +000060 20914FB8 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 |................................| +000080 20914FD8 00000000 00000000 2090F6BC 00000000 2090F28C 00000000 2090F4A4 00000000 |..........6.......2.......4u....| +0000A0 20914FF8 00000000 00000000 A099FF10 A09C4A58 A09D0FD8 A09D7E98 A09D2B08 A09D9A78 |.........r.........Q..=q........| ⋮