Rational Developer for System z
Enterprise PL/I for z/OS, Version 3.8, Programming Guide

Locating CONTROLLED variables

CONTROLLED variables are essentially LIFO stacks, and each CONTROLLED variable has an "anchor" that points to the top of that stack. The key to locating a CONTROLLED variable is to locate this anchor, and its location depends on the compiler options as described below.

In the rest of this discussion of CONTROLLED variables, the program source will be the same program as above, but with the storage class changed to CONTROLLED:

Compiler Source
  Line.File
     2.0      test: proc options(main);
     3.0
     4.0        dcl a fixed bin(31) controlled;
     5.0        dcl b fixed bin(31) controlled;
     6.0
     7.0        on error
     8.0          begin;
     9.0            call plidump('TFBHC');
    10.0          end;
    11.0
    12.0        allocate a, b;
    13.0        a = 0;
    14.0        b = 29;
    15.0        b = 17 / a;

Under NORENT WRITABLE

The result of the compiler MAP option looks like this, except that again there is actually one more column on the right and the columns are actually spaced much further apart:

* * * * *   S T O R A G E   O F F S E T   L I S T I N G   * * * * *
 IDENTIFIER DEFINITION ATTRIBUTES

 A          1-0:4      Class = static,  Location = 8 : 0x8 + CSECT ***TEST2
 B          1-0:5      Class = static,  Location = 12 : 0xC + CSECT ***TEST2

Note: that these lines describe the location of the anchors for A and B (not the location of A and B themselves). So, A’s anchor is located at hex 08 into the static CSECT for the compilation unit TEST while B’s anchor is located at hex 0C.

If PLIDUMP is called with the B option, it will include a hexadecimal dump of static storage for each compilation in the current calling chain. This will look like (again with the right columns cutoff):

Static for procedure TEST    Timestamp: . . .

  +000000 0FC00A88  0FC00DB0 0FC00AA8 102B8A30 102B8A50
  +000020 0FC00AA8  0FC00A88 00444042 00A3AE01 0FC009B0
  +000040 0FC00AC8  6E3BFFE0 00000000 00000000 00000000

So, A’s anchor is at 102B8A30 and B’s is at 102B8A50. But since these are CONTROLLED variables, their storage was obtained via ALLOCATE statements, and hence these addresses point into heap storage. But If PLIDUMP is called with the H option, it will include a hexadecimal dump of heap storage. This will look like (again with the right columns cutoff):

Enclave Storage:
  Initial (User) Heap
    +000000 102B7018  C8C1D5C3 0FC0F990 0FC0F990 00000000
      . . .
    +001A00 102B8A18  102B7018 00000020 0FC00A90 00000014
                      00000000 00000000 00000000 00000000
    +001A20 102B8A38  102B7018 00000020 0FC00A94 00000014
                      00000000 00000000 0000001D 00000000

Since A’s anchor was at 102B8A30, A has the hex value 00000000, and since B’s anchor was at 102B8A50, B has the (expected) hex value 0000001D.

Under NORENT NOWRITABLE(FWS)

The result of the compiler MAP option under these options looks like this, except that again there is actually one more column on the right and the columns are actually spaced much further apart:

 * * * * *   S T O R A G E   O F F S E T   L I S T I N G   * * * * *
 IDENTIFIER DEFINITION ATTRIBUTES

 A          1-0:4      Class = automatic,  Location = 236 : 0xEC(r13)
 B          1-0:5      Class = automatic,  Location = 240 : 0xF0(r13)

Note: under these options, there is an extra level of indirection in locating CONTROLLED variables, and hence the lines above describe the locations of the addresses of the anchors for A and B. So, the address of A’s anchor is located at hex EC into the automatic for the block TEST while B’s is located at hex F0.

Since PLIDUMP is called with the B option, it will include a hexadecimal dump of automatic storage for each block in the current calling chain. This will look like (again with the right columns cutoff):

 Dynamic save area (TEST): 102973C8
  +000000 102973C8  10000000 10297188 00000000 8FC007DA
          ....
  +0000E0 102974A8  0FC00998 00000000 00000000 102B8A40
                    102B8A28 10297030 102977D0 8FDF3D7E

So, the address of A’s anchor is 102B8A40 and B’s is 102B8A28.

Since PLIDUMP was also called with the H option, it will include a hexadecimal dump of heap storage. This will look like (again with the right columns cutoff):

 Enclave Storage:
    Initial (User) Heap
      +000000 102B7018  C8C1D5C3 0FC0F990 0FC0F990 00000000
        . . .
      +001A00 102B8A18  102B7018 00000018 00000000 0FC00A78
                        102B8A80 00000000 102B7018 00000018
      +001A20 102B8A38  102B8A20 0FC00A74 102B8A60 00000000
                        102B7018 00000020 102B8A40 00000014
      +001A40 102B8A58  00000000 00000000 00000000 00000000
                        102B7018 00000020 102B8A28 00000014
      +001A60 102B8A78  00000000 00000000 0000001D 00000000
                        00000000 00000000 00000000 00000000

Since B’s anchor address was at 102B8A28, B’s anchor is at 102B8A80, and B has, as expected, the hex value 0000001D or decimal 29.

Under NORENT NOWRITABLE(PRV)

The MAP listing when compiled with these options would look like this:

* * * * *   S T O R A G E   O F F S E T   L I S T I N G   * * * * *
 IDENTIFIER DEFINITION ATTRIBUTES

 ***TEST3     1-0:4  Class = ext def,  Location = CSECT ***TEST3
 ***TEST4     1-0:5  Class = ext def,  Location = CSECT ***TEST4
_PRV_OFFSETS  1-0:1  Class = static,   Location = 8 : 0x8 + CSECT ***TEST2

The key here is the last line in this output: _PRV_OFFSETS is a static table that holds the offset into the PRV table for each CONTROLLED variable. This static table is generated only if the MAP option is specified.

To interpret this table, the compiler will also produce, immediately after the block names table, another, usually small, listing, which for our program would look like:

           PRV Offsets

    Number   Offset Name
         1        8 A
         1        C B

This table lists the hex offset within the runtime _PRV_OFFSETS table for each of the named CONTROLLED variables. The block number (in the first column) can be used to distinguish variables with the same name but declared in different blocks.

Since the _PRV_OFFSETS table is in static storage (at hex offset 8) and since PLIDUMP was called with the B option, it will appear in the dump output, which would look like this:

Static for procedure TEST    Timestamp: . . .
  +000000 10908EC8  02020240 00000005 6DD7D9E5 6DD6C6C6
                    00000000 00000004 D00000A0 00100000
  +000020 10908EE8  6E3BFFE0 00000000 00000000 00000000
                    00000000 90010000 00000000 00000000

So, the offset of A in the PRV table is 0, and the offset of B in the PRV table is 4. Note also the eyecatcher "_PRV_OFF" that occupies the first 8 bytes of the _PRV_OFFSETs table.

The PRV table is always located at offset 4 within the CAA which, since PLIDUMP was called with the H option, will be in the dump output and which looks like:

Control Blocks Associated with the Thread:
  CAA: 0A7107D0
   +000000 0A7107D0  00000800 0ADB7DE0 0AD97018 0ADB7018
                     00000000 00000000 00000000 00000000

So, the address of the PRV table is 0ADB7DE0, and it will also be in the dump output amongst the HEAP storage:

 Enclave Storage:
    Initial (User) Heap
      +000000 102B7018  C8C1D5C3 0FC0F990 0FC0F990 00000000
        . . .
      +000DC0 0ADB7DD8  00000000 00000000 0ADB8A38 0ADB8A58
                        0ADB7018 00000488 00000000 00000000

So, the PRV table contains 0ADB8A38 0ADB8A58 etc, and since, as derived from the _PRV_OFFSETS table, A’s offset into the PRV table is 0 and B’s offset is 4, these are also the addresses of A and B respectively.

These addresses will also appear in the HEAP storage in the dump:

  Enclave Storage:
    Initial (User) Heap
      +000000 102B7018  C8C1D5C3 0FC0F990 0FC0F990 00000000
        . . .
      +001A00 0ADB8A18  00000000 00000000 0ADB7018 00000020
                        00000000 00000014 0A7107D4 00000000
      +001A20 0ADB8A38  00000000 00000000 0ADB7018 00000020
                        00000004 00000014 0A7107D4 00000000
      +001A40 0ADB8A58  0000001D 00000000 00000000 00000000
                        00000000 00000000 00000000 00000000

So, since A’s address is 0ADB8A38, its hex value is, as expected, 00000000, and since B’s address is 0ADB8A58, its hex value is, also as expected, 0000001D.


Terms of use | Feedback

This information center is powered by Eclipse technology. (http://www.eclipse.org)