CONTROLLED 変数は本質的に LIFO スタックであり、それぞれの CONTROLLED 変数は、そのスタックの先頭を指す「アンカー」 を持っています。 CONTROLLED 変数を検出する秘訣はこのアンカーの位置を検出すること であり、下記のように、その位置はコンパイラー・オプションによって異なります。
CONTROLLED 変数に関するこの説明の残りの部分では、プログラム・ソース は上記と同じプログラムですが、ストレージ・クラスが 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;
コンパイラー MAP オプションの結果は、この場合も、実際には右側にもう 1 つ列 があること、列の間のスペースはもっと離れていることを除き、以下のようになります。
* * * * * 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
注: これらの行は、(A および B それ自体の場所ではなく) A および B のアンカーの場所を記述しています。 したがって、A のアンカーはコンパイル単位 TEST の静的 CSECT の中の 16 進オフセット 08 の位置にあり、B のアンカーは 16 進オフセット 0C の位置にあることになります。
PLIDUMP が B オプションを指定して呼び出されている場合、 現行の呼び出しチェーン内のそれぞれのコンパイルごとに、静的ストレージ の 16 進ダンプが含まれています。 これは、以下のようになります (これも、右側の列が省略されています)。
Static for procedure TEST Timestamp: . . . +000000 0FC00A88 0FC00DB0 0FC00AA8 102B8A30 102B8A50 +000020 0FC00AA8 0FC00A88 00444042 00A3AE01 0FC009B0 +000040 0FC00AC8 6E3BFFE0 00000000 00000000 00000000
したがって、A のアンカーは 102B8A30 にあり、B のアンカーは 102B8A50 にあることになります。 しかし、CONTROLLED 変数があるため、これらのストレージは ALLOCATE ステートメント を使用して取得されており、そのため、これらのアドレスはヒープ・ストレージ内を指しています。 しかし、PLIDUMP が H オプションを指定して呼び出されている場合は、 ヒープ・ストレージの 16 進ダンプが含まれることになります。 これは、以下のようになります (これも、右側の列が省略されています)。
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
A のアンカーが 102B8A30 にあったので、A は 16 進 00000000 を持ち、B のアンカーが 102B8A50 にあったので、B は (予想通りの) 16 進 0000001D を持つことになります。
これらのオプションを指定したコンパイラー MAP オプション の結果は、この場合も、実際には右側にもう 1 つ列 があること、列の間のスペースはもっと離れていることを除き、以下のようになります。
* * * * * 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)
注: これらのオプションを指定した場合、CONTROLLED 変数の位置を指定するために、追加の 間接指示のレベルがあり、そのため、上記の行は A および B のアンカーのアドレスの位置 を記述しています。 したがって、A のアンカーのアドレスはブロック TEST の AUTOMATIC 内の 16 進 EC の位置にあり、一方 B のアンカーは 16 進 F0 にあることになります。
PLIDUMP が B オプションを指定して呼び出されているため、 現行の呼び出しチェーン内のそれぞれのブロックごとに、自動ストレージ の 16 進ダンプが含まれています。 これは、以下のようになります (これも、右側の列が省略されています)。
Dynamic save area (TEST): 102973C8
+000000 102973C8 10000000 10297188 00000000 8FC007DA
....
+0000E0 102974A8 0FC00998 00000000 00000000 102B8A40
102B8A28 10297030 102977D0 8FDF3D7E
したがって、A のアンカーのアドレスは 102B8A40 になり、B のアンカー のアドレスは 102B8A28 になります。
PLIDUMP が H オプションも指定して呼び出されているので、 ヒープ・ストレージの 16 進ダンプが含まれることになります。 これは、以下のようになります (これも、右側の列が省略されています)。
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
B のアンカーのアドレスが 102B8A28 にあり、B のアンカー が 102B8A80 にあるので、B は、予想通り 16 進 0000001D、つまり 10 進 29 になります。
これらのオプションを指定してコンパイルした場合の MAP リストは、以下のようになります。
* * * * * 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
ここでのキーは、この出力の最後の行です。 PRV_OFFSETS は、それぞれの CONTROLLED 変数についての PRV テーブル 内でのオフセットを保持する静的テーブルです。 この静的テーブルは、MAP オプションが指定された場合にのみ生成されます。
このテーブルを解釈するために、コンパイラーは、ブロック名テーブルのすぐ後に、通常は小さな 別のリストも生成します。このリストは、このサンプルでは、以下のようになります。
PRV Offsets
Number Offset Name
1 8 A
1 C B
このテーブルには、名前が示された CONTROLLED 変数ごとに、ランタイム _PRV_OFFSETS テーブルでの 16 進オフセットがリストされます。 ブロック番号 (最初の列) を使用して、同じ名前であるが、異なるブロックに宣言されている変数 を区別することができます。
_PRV_OFFSETS テーブルは静的ストレージ内 (16 進オフセット 8) にあり、PLIDUMP が B オプションを指定して呼び出されたため、以下に示すようなダンプ出力が表示されます。
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
したがって、PRV テーブル内の A のオフセットは 0 になり、PRV テーブル内の B のオフセットは 4 になります。_PRV_OFFSETS テーブルの最初の 8 バイトを占めている目印「_PRV_OFF」にも注目してください。
PRV テーブルは、常に CAA 内のオフセット 4 の位置にあり、PLIDUMP が H オプション を指定して呼び出されたため、ダンプ出力に表示され、以下のようになります。
Control Blocks Associated with the Thread:
CAA: 0A7107D0
+000000 0A7107D0 00000800 0ADB7DE0 0AD97018 0ADB7018
00000000 00000000 00000000 00000000
したがって、PRV テーブルのアドレスは 0ADB7DE0 になり、ヒープ・ストレージ内の ダンプ出力にも表示されます。
Enclave Storage:
Initial (User) Heap
+000000 102B7018 C8C1D5C3 0FC0F990 0FC0F990 00000000
. . .
+000DC0 0ADB7DD8 00000000 00000000 0ADB8A38 0ADB8A58
0ADB7018 00000488 00000000 00000000
したがって、PRV テーブルには 0ADB8A38 0ADB8A58 などが入って おり、_PRV_OFFSETS テーブルから得られたとおり、PRV テーブル内での A のオフセットは 0 になり、B のオフセットは 4 になります。 これらは、それぞれ A と B のアドレスでもあります。
これらのアドレスは、ダンプ内のヒープ・ストレージにも表示されます。
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
したがって、A のアドレスは 0ADB8A38 で、その 16 進は予想通りの 00000000 になり、B のアドレスが 0ADB8A58 なので、 その 16 進値も予想通りの 0000001D になります。