ダンプ・リスト解析入門(番外編):正しいアドレスなのにS0C4でABENDしている??

MVCL命令でデータの移動先アドレスや移動するデータの長さを間違えた場合、データの移動中にプログラム割り込みを起こしS0C4でABENDすることがあります。命令で指定したレジスターは、ABENDした時点の移動元や移動先のアドレス、残りの領域長やデータ長を示します。

この命令は、GR14が示すアドレスの領域内データをGR0が示すアドレスの領域にコピーするものです。領域の長さは対となっているGR1およびGR15に入っています。この命令実行中に次に示すようなPSWとレジスターでABENDしました。

ABENDした時点のGR0はx0000A000、GR14はx00008EBCで残りデータ長はx60バイトを示しています。SYSUDUMPに出力された移動元と移動先の領域内容は次の通りでした。

プログラムではGR14が示す移動元は、自プログラム領域内でアドレスと長さの指定には問題がありません。となれば移動先のアドレスxA000が問題となったものと考えられます。しかし、ダンプ・リストには問題であろうアドレスxA000は有効なストレージ領域として出力されています。仮想アドレスとして存在しているのにどうして不正アドレスでS0C4してしまうのか?という疑問も生じます。

結論から言うと、この場合のxA000は確かに誤ったアドレスなのです。プログラム・コードを見るとGETMAINで長さを4000バイトとして移動先の領域を割り振っているのに、MVCL命令は4096バイトの長さで実行しています。そのため、4000バイト移動し終わった時点でABENDしたものです。
アドレスxA000の領域は存在しないのですからダンプには出てこないはずですが、出てきてしまっているために、それならば有効な仮想記憶域ではないのか?と思ってしまうわけです。
手元にプログラム・コードがあって、単純なミスのようなバグであればダンプがどうであれ、簡単に原因はわかりますが、複雑なプログラムであったり、過去に作られたもので内容もよくわからないといったような場合では、ダンプされた領域の内容から問題を起こしたモジュールや箇所を特定したい場合もあります。プログラムの規模が大きくなると、原因を作った箇所と実際にABENDしたモジュールが違うと言ったことはよくあることです。ダンプ上でxA000は、Storage not availableであるとはっきり出ていればいいのですが、上記のようにダンプにも領域として出てきてしまうと、どうしてこのアドレスでS0C4になるのか?と考えてしまうかも知れません。

実はダンプに出ているxA000からの領域は、このプログラムがABENDした後にMVSのABEND処理によって割り振られた領域です。このケースではSYSUDUMP(あるいはSYSABEND)を出力するための作業域、関連するモジュールのローディングなどに使われていました。ダンプ・リストはABENDした時点の空間内の記憶域を編集して出力しますが、ABENDそのものを処理したりダンプを出力するためにMVSのRTMなど関連するコンポーネントのモジュールが実行されます。そのため、ABEND発生からダンプのためにメモリー内容が読み取られるまでの間にOSの作業域として空間内の領域が使用され、そこがたまたまアプリケーション・プログラムが割り振った領域の直後に続いて割り振られると、ダンプ上では有効な仮想記憶域が続いているように見えるのです。
その後にOSのモジュール名らしきものやABEND処理に使われそうな内容の文字列などが入っていれば当たりもつきますが、ヌル・データなどがある程度続いていたりすると元々GETMAINしていたアプリケーションの領域ではないのか?とも思えてしまうのです。このケースではSYSUDUMPではなくSYSMDUMPでバイナリー・ダンプの出力に変えたところ、xA000の領域はダンプ上存在せず Storage not available となっていました。SYSMDUMPはフォーマットしないのでより少ない作業域で処理されたものと考えられます。

もし、MVCL命令実行中にABENDしたので関連するレジスターからダンプでストレージ内容を確認し、仮想記憶域として出力されているからS0C4するようには見えないが?と思ったら、データの移動元や移動先アドレスがちょうどページの始まりを示すきりのいいアドレス値になっていないかを確認してみて下さい。このケースのようにxA000など仮想ページの開始アドレスつまりページ・バウンダリーになったアドレスであれば、間違いなくデータ移動中に有効なページを超えてデータを処理しようとしたものです。GETMAINしていない領域でも、あるいはFREEMAINしてしまった領域でも、ページの1部でも有効に残っていればそのページの4KBの中であればS0C4にはなりません。そのページを超えて次のページが割り振られていないと、そこでS0C4になります。

いずれにしてもダンプ・リスト(特にSYSUDUMPとSYSABEND)に出てくるメモリー内容は、純粋にアプリケーション・プログラムでだけ使われている領域だけではなく、ABENDした時にはなかったけどABEND処理の過程でリージョン内の領域が割り振られて使われた結果、ダンプに出てくる領域もあるのだということを知った上でダンプを調べると余計な疑問を持たずに済みます。原因がなかなか掴めないと、どうしても他の誰かが悪いのでは?と考えたくなりますが、プログラムがABENDする原因は99.999%自分の作ったプログラムにあるのだと考える方が無難です。