きどたかのブログ

いつか誰かがこのブログからトラブルを解決しますように。

Segment Translation Exception(セグメント変換例外)の考察

 営業日にして10日間であったが、

日本に帰国していたとき、ラストのほうでダンプを読んでいた。

 

そこでひとつ間違えたことがあった。

0C4の10や11は、Failing Instructionを通り過ぎないそうなのだ。

だから、ILC分戻るのは間違いだった。

その間違いは、インストラクションの誤認、汎用レジスタの誤認につながっている。

通り過ぎる場合と通り過ぎない場合がある。それは知ってた。

4(保護例外)のケースばかり見てたから間違えた。

 

あのときTEA(Translation Exception Address)を確認しなかったのもまずい。

TEAについて書いてるパワポをその時見てなかった。

存在知っていて読んでいたのに、別の資料を見ながらやっていた。

でもSYSTRACEは見ていたのだから、TEAそのものがでていたはずだ。

それを確認していれば、レジスタのもってるアドレスと違うと気付けたはず。

 

ただ、LEDATAで見てる関数名に間違いはないので、

入力データに依存してABENDするのは間違いない。

そういう意味で自分はそのとき「最後にいい仕事をした」と言ったほどだ。

ここでいう「最後」ってのは、翌日また米国に戻るからってこと。

このときの所要時間は6時間。

なんか分からないけどABENDするは、

たかがSQLコメントごときでABENDする問題に変わった。

 

普通ならこんな確実な発生条件を見つけたら問い合わせて終わりなんだが、

諸事情でそういうことにもいかない。

さてどうしよう。

 

基本的にこれは環境差異からくる問題という認識でやっている。

しかし基本的にはコピーだ。だからモジュールが変わってるわけがない。

バイナリで同一であるはずだ。

SYSPLEXからMONOPLEXに変わっている。

ふむ、だが、だからどうした。

SQLコメントになんらかの処理をするしょぼい関数に

そんな違いが影響すると考えるのは不自然だ。

 

追加で調査するとしたらまず何をやろうか。

制御レジスタを調べたい。

セグメント変換例外の側からにじりよって調べたいのだ。

PSWのDAT Modeや、制御レジスタ(0,1,7,13あたり)、

セグメント・テーブルやセグメント・テーブルに関係するコントロール・ブロックとか。

これは現状分析の深堀り。

2環境の差を見ることで意味がでてくることを期待している。

 

セグメント変換例外が発生する条件は二つ。

仮想アドレスのセグメント・インデックス部分で指定されているセグメント・テーブル・エントリがセグメント・テーブルの範囲外である場合。

セグメント・テーブル・エントリのセグメント無効ビットが1の場合。

 

あと、この話は64bitで、64bit Virtual Address Spaceのトランスレーションになる。

64bitの仮想アドレスは、64bitで表現される。

そのうち、segment indexの部分はbits 33-43だ。

 

この辺の超細かい話は、

z/Architecture Priciples of OperationのFigure 3-11. Translation Processを見るといい。

どういうときにセグメント変換例外(10)になるかが分かる。

さきほどの二種類の発生条件のうち、1つ目は上限と下限が存在するため、

より具体的には3パターン存在する。

とりあえず、どのパターンだったのか調べてみたくなる。

 

もうひとつオマケにTLB(Translation Lookaside Buffer)というのがあるようだ。

しかしTLBを使用する部分においてセグメント変換例外になるフローになってない。

Figure 3-11. Translation Processはよくできてる。

 

幸いにも必ず同じポイントでABENDする。

だから、エントリーポイントからのオフセットは絶対に同じ。

環境によってエントリーポイントが違う可能性はあるので、

そこはダンプ取って調べれば済むこと。

まさかとは思うが、インストラクション・アドレスが原因かってのもある。

 

そんでもって試したいのはSLIP SET,IFコマンド。

インストラクション・フェッチ(IF)のタイミングでダンプを取れる。

だがこのIFオプションをまだ使った経験がない。

取るとしたらまずは2箇所。

失敗するインストラクションと、関数のエントリポイント。

 

ダンプで見るところは、上述のような話の部分のほかに・・・

ぶっちゃけセグメント・テーブルはいまどういう状況なのかとか。

LEDATAでR1にも注目したい、きっと引数リストが入ってるはず。

 

あとは結局だれが使えないアドレスをレジスタに突っ込んだか?

SYSTRACEを遡っていくしかないかな。

それともLISTのINSTRUCTIONオプションで見てみるか。

エントリポイントから順番におっていけば、

アセンブラレベルでロジックが分かるだろう。

なーにきっと簡単さ、最後にそのレジスタにLOAD ADDRESSしたとこを見ればいい。

 

なんで使えないアドレスになったか?

自分の感覚だとC/C++のプログラムがセグメント・インデックスをメンテしてるとは思えない。

たとえばmallocはサイズしか引数にない。

そうなると、裏で控えてるのはLE。

LEがどういう形でメモリを取ってくるのか。

GETMAINとかCPOOLとかIARV64の話にきっとなる。

RUNOPTSでなんかいいやつなかったかな・・・。

たぶんHEAPCHKだと思う。

そんでもって、LEDATAのHPTとかで見る。

 

そもそもあれは非常に奇妙なトレースバックだ。

なんであんなしょぼい関数のみのDSAしかないTCBがいるんだ。

呼び元のTCBも見といたほうがよかったな。

 

素人なりに考えてもいろいろと考えることがある。