SunOS 4.xでMOを使うには |
YAMAMORI Takenori ●yamamori |
問題のscsi_slave()という関数の実体が存在するのは, カーネルの/sys/sun4m/OBJ/scsi_confsubr.o (※注) というオブジェクトファイルです. これは,実際にnmコマンドでシンボルテーブルを表示させて確認することができます.
このscsi_slave()関数をラップし,DTYPE_OPTICALを強制的にDTYPE_DIRECTに 書き換える方法を以下に説明します.
まず,/sys/sun4m/OBJ/scsi_confsubr.o内のscsi_slave()を, 何らかの方法でscsi_slavE()という関数名に修正し, これをscsi_confsubr_E.oというファイル名で保存します. (具体的な方法は後述します)
次にwrap_scsi_confsubr.cというラップ用のプログラムを作成し, ここにscsi_slave()という,もとの関数名を使って関数を記述します. このscsi_slave()の中から,scsi_confsubr_E.oの中のscsi_slavE()を呼び出し, その直後にDTYPE_OPTICALをDTYPE_DIRECTに書き換えるのです.
最後にwrap_scsi_confsubr.cをコンパイルしてできるwrap_scsi_confsubr.oと, scsi_confsubr_E.oとを「ld -r」コマンドでリンクし, scsi_confsubr_mo.oというファイルを作成します. そしてこのscsi_confsubr_mo.oを,本来の/sys/sun4m/OBJ/scsi_confsubr.oと 置き換えてやればよいのです.
/sys/sun4m/OBJ/scsi_confsubr.o内で定義された本来のscsi_slave()を, scsi_slavE()という関数名に修正するには,次に示す通り, scsi_confsubr.oの中のシンボルテーブルをバイナリファイルのレベルで書き換えます. なお,以降の作業では,strings, headなどについて, 所定のオプションを使用するためにGNU系のコマンドを使用する必要があります.
まず,scsi_slaveというシンボルが埋め込まれているバイナリ位置を見つけます. SunOS 4.xの場合は,シンボル名の先頭にアンダースコア(_)が付くため, 実際には「_scsi_slave」というシンボル名になります. 調べるのはあくまでシンボル自体のバイナリ位置であり, シンボルが定義している関数のアドレスではありません. したがって,ここではnmコマンドではなく,下図のようにstringsコマンドを使います. ここでは,「-a」オプションでバイナリファイル全体を対象とし, さらに「-t d」オプションを指定して, 文字列の存在するアドレスを10進で表示させています. なお,ここに示すアドレス値は,筆者の環境における実行例ですが, 具体的な値はカーネルアーキテクチャやSunOS 4.xのバージョンによって異なります.
…省略… 4292 _phz 4297 _wantin 4305 _hostnamelen 4318 _scsi_slave ← シンボルテーブルのscsi_slave 4330 _scsi_ncmds 4342 _scsi_rinit 4354 _bufalloc …省略… |
以上の結果から,シンボルテーブルの「_scsi_slave」の先頭の「_」は アドレス4318に存在し,ここから順に後ろに数えて, 末尾の「e」はアドレス4328に存在することがわかります. そこで,これを「E」に書き換えればよいのです. バイナリファイルの修正は,適当なバイナリエディタがあればそれを利用しても よいでしょう.筆者は,head,echo,tailコマンドを使って書換えを行ないました. このコマンドは次に示すMakefileの中に直接記述します.