PLIDUMP Subroutine

Purpose

Allows you to create a formatted dump of selected parts of storage used by your program.

Syntax

CALL PLIDUMP (character-string-expression 1,character-string-expression 2);

Parameters

character-string-expression 1 is a dump options character string consisting of one or more of the following:
Note: For compatibility, any valid IBM PL/I character string is allowed, but only the following character string options are allowed.
C Continue. The routine continues after the dump.
F Add key information in the dump for KSDS files accessed by the run-time system.
H Display heap data in PLIDUMP.
S Stop. The enclave terminates with a dump.
T TRACEBACK.

T, and C are the default options.

character-string-expression 2 is a user-identified character string up to 80 characters long that is printed as the dump header.

Description

PLIDUMP dumps information about the calling path to the current location and other data to a formatted dump.

Use one of these output choices to get the maximum amount of information for PLIDUMP.

  • Set CODEWATCH_STBPATH
  • Place the .stb files into the same directory as your the .dlls being executed.

To generate symbols and source line information using PLIDUMP, compile your program with -deb to generate the necessary .stb files. This information is useful when moving from test to production.

PLIDUMP can also provide KEY information for any KSDS files that have been accessed by the PL/I run-time system.

Examples

This shows an example of a PL/I routine calling PLIDUMP to produce a Language Environment dump. In this example, the main routine PLIDMP calls PLIDMPA, which then calls PLIDMPB. The call to PLIDUMP is made in routine PLIDMPB.

%PROCESS MAP GOSTMT SOURCE STG LIST OFFSET LC(101);
 PLIDMP: PROC OPTIONS(MAIN) ;

   Declare   (H,I) Fixed bin(31) Auto;
   Declare   Names Char(17) Static init('Bob Teri Bo Jason');
   H = 5;	 I = 9;
   Put skip list('PLIDMP Starting');
   Call PLIDMPA;

     PLIDMPA: 	PROC;
       Declare (a,b) Fixed bin(31) Auto;
       a = 1;	 b = 3;
       Put skip list('PLIDMPA Starting');
       Call PLIDMPB;

         PLIDMPB:  PROC;
           Declare  1 Name auto,
             2 First   Char(12) Varying,
             2 Last    Char(12) Varying;
           First = 'John';
           Last = 'Thompson';
           Put skip list('PLIDMPB Starting');
           Call PLIDUMP('TBFC','PLIDUMP called from procedure PLIDMPB');
           Put Data; 
         End PLIDMPB;
     End PLIDMPA;
 End PLIDMP;

This example calls PLIDUMP with the F option in two different places.

 DemoBlks: proc options (main);
   
    /********************************************/
    /* Files                                    */
    /********************************************/    
    dcl KSDSFILE     file 
     env(VSAM GENKEY KEYLOC(31) KEYLENGTH(6) recsize(80));        
    dcl NOTTHERE     file;
    dcl SYSUT1       file record input;    

    /********************************************/
        /* Variables                                */
    /********************************************/
    dcl eof_sysut1   bit(1) init('0'b);
    dcl good_record  bit(1);
    dcl mykey        char(06);
    dcl myrec1       char(80);      
    dcl sysut1_rec   char(100) varying;    
                
    on error
      begin;
        on error system;
        call PLIDUMP('FS'); 
      end;

    on key(KSDSFILE)
      begin;
        good_record = '0'b;
        put skip list('KSDSFILE record not found');
        call PLIDUMP('FC'); 
      end;

    on undefinedfile(NOTTHERE);
      begin;
      end;

    on endfile(SYSUT1) eof_sysut1 = '1'b;

    call PLITEST('shlib DEMOBLKS.dll;env DEMOBLKS;br mylabel;br %exit[det;q];c','',1);
        mylabel:

    open file(SYSPRINT);
    open file(SYSUT1);    
    open input file(NOTTHERE);     
    open file(KSDSFILE) update keyed;
      
    /* Call PLIDUMP w/o 'F' option to demonstrate no  */
        /* File Control blocks generated in first PLIDUMP */

    call PLIDUMP('C');    

    /* Run until an ERROR is encountered and generate a PLIDUMP */        
        /* that can be used to diagnose the cause of the problem   */
        /* Note:  There are intentionally more than one problem   */
        /*        generated in this demo in order to show all     */
        /*        functionality                                   */

    put skip list('Starting DEMOBLKS Key processing');
    put skip;

    read file(SYSUT1) into (sysut1_rec);                  
    do while(^eof_sysut1);
        good_record = '1'b;
        read file(KSDSFILE) into (myrec1) key(substr(sysut1_rec,1,6));
        if (good_record) then
            put skip list('processing KSDSFILE record: ' || myrec1);
        read file(SYSUT1) into (sysut1_rec);              
    end;

    put skip list('Did you find what went wrong??');    

    close file(KSDSFILE);
    close file(SYSUT1);

 end DemoBlks;

When executing this example, all files show the last operation that took place.

All files also show the optional additional information about the operation via the "File Status" bytes. Further, the example when run would show a 9/13 (bad filename), and also a "23" - record not found on a read. These file statuses equate to COBOL File Status bytes, and if they start with "9" they equate to a run-time error. The hyperlinks to that information are very useful.

The buffers for VSAM files contain the results of the last IO operation. Buffers for QSAM files may contain the actual buffer that was used on the last file I/O operation. This is caused by the fact that there could be a variable allocated on the stack (automatic) that no longer is a valid address, was dynamically allocated and has since been freed. An attempt is made to display whatever is at the address pointed to, that this may or may not be reliable depending on the structure of your program and what was in the call stack at the time of the call to PLIDUMP. If you want to always have reliable information in the buffer display for QSAM files, ensure that they are always reading into or writing from STATIC variables.

The "varying item" field displayed as a 0 or 1 can be useful in determining why there may be a pair of length bytes displayed at the start of the buffer at the time of the PLIDUMP.

Restrictions

32-bit Windows only:

Scenario 1:
COBOL1 calls 
               PLISUB1 calls 
                              PLISUB2 calls PLIDUMP()

In this scenario, PLIDUMP contains all the information for PLISUB1 and PLISUB2 but has no indication that COBOL1 exists, nor that it had called PLISUB1.

Scenario 2:
PLIMAIN calls 
COBOL1 calls 
                              PLISUB1 calls 
                                             PLISUB2 calls PLIDUMP() 

In this scenario, PLIDUMP contains all the information for PLISUB1 and PLISUB2 but has no indication that PLIMAIN and/or COBOL1 exist.