NOEMBLEM/エンブレムが設定されていません。

メールの詳細(メール表示)

件名:

Re: phi.soへの依存に関して

差出人: Yuya Katoさん <yuya-ml…>
送信日時 2003/10/27 00:49
ML.NO [ap-list:3156]
本文:

Yuya@説得モードです。:-)
長文で失礼します。

On Sun, 26 Oct 2003 18:45:18 +0900
Kazuhiro Yoshida <moriq@…> wrote:

> 例えば ap_mPhi を公開せずに Ruby側の Phi (module) として拾う、
> という形ですね。
> やってみないとわかりませんが、全部Rubyインタプリタ経由にする
> のはちと難しい…かも。
はい。そういう事です・・・が、やはり難しいですか。

> phi.so をふたつに分けて、例えば phi_core.so と phi.so にして、
> phi.so もほかの拡張ライブラリと同列にする…というのでは解決策
> にならないのか。
間接的にインポートされると、さらに複雑になるのでご勘弁を。:-)

> 拡張ライブラリが他の拡張ライブラリに依存していることが問題な
> のであれば、上記のふたつに分ける方法を使って、見かけ上は直接
> インポートしてない状態にはできそう。
rb_require(foo)などで依存する分には、Exerb的になんら問題
ないのですが、インポートされるとちょっと。

> うう。
> Apollo対応コードの行っていることを説明していただけますか?
> ソースを読めっ! でもかまいませんが。あ、でも C++ わかんない^^;
ソースを読めっ!というのは、嘘で、以下解説。
あ、ちなみにExerbはほとんどC言語なC++で書かれています。
変数宣言をブロックの頭でやらなければならないのが、苦手なんです。


ではでは、解説を始めましょう。タララッタッタッタッタ♪
(3分クッキングの音楽にあわせて)
以下、固定幅フォントでお楽しみください。

まずは、Exerbの仕組みから。
foo.rbというスクリプトとbar.soという拡張ライブラリを含む
実行ファイルをExerbで作るとします。図解するとこんな感じ。

+------------+
| Exerb Core |
+------------+
| Archive |
| +--------+ |
| | foo.rb | |
| +--------+ |
| | bar.so -------> mswin32-ruby18.dll
| +--------+ |
+------------+

通常の拡張ライブラリは、mswin32-ruby18.dllをダイナミックリンク
するようになっています。
そこでExerbは、mswin32-ruby18.dllへのリンクをねじ曲げて、
mswin32-ruby18.dllと同等の機能を持つExerb Coreへリンクします。

+------------+
| Exerb Core |<-+
+------------+ |
| Archive | |
| +--------+ | |
| | foo.rb | | |
| +--------+ | |
| | bar.so -----+
| +--------+ |
+------------+

これで、mswin32-ruby18.dllの存在しない環境でも、拡張ライブラリ
が使えるようになります。
と、ここまでがExerbの仕組みの解説。

さてと、ここから本題。
phi.so、jpeg.so、そしてそれを利用するfoo.rbを含む実行ファイルを
生成したとします。jpeg.soはphi.soをインポートしています。
図解すると下記のような感じ。

+-------------+
| Exerb Core |
+-------------+
| Archive |
| +---------+ |
| | foo.rb | |
| +---------+ |
| | phi.so ---------> mswin32-ruby18.dll
| +---------+ |
| | ---------> mswin32-ruby18.dll
| | jpeg.so ---------> phi.so
| +---------+ |
+-------------+

さて、これも同じようにmswin32-ruby18.dllへのダイナミックリンクを
ねじ曲げます。するとこんな感じ。

+-------------+
| Exerb Core | <-+<-+
+-------------+ | |
| Archive | | |
| +---------+ | | |
| | foo.rb | | | |
| +---------+ | | |
| | phi.so ------+ |
| +---------+ | |
| | ---------+
| | jpeg.so ---------> phi.so
| +---------+ |
+-------------+

あれあれ、phi.soへのリンクが残っています。このままだと実行時に
実行ファイル内のphi.soではなく、外側のphi.soを探しに行ってしまいます。
もちろん、外側に(通常は)phi.soは無いので、リンクに失敗します。
そこで、Exerb内のApollo対応コードの登場です。対応コードにより
jpeg.soを書き換え、実行ファイル内のphi.soを参照するようになります。

+-------------+
| Exerb Core | <-+<-+
+-------------+ | |
| Archive | | |
| +---------+ | | |
| | foo.rb | | | |
| +---------+ | | |
| | ------+ |
| | phi.so | | <-+ |
| +---------+ | | |
| | ------+ |
| | jpeg.so ---------+
| +---------+ |
+-------------+

これで正常にリンクできるようになりました。ざっと説明すると
こんな感じです。

具体的にApollo対応コードが何をやっているかと言うと:

1. phi.soというファイルがrequireされたら、その一時ファイル名
を保存する。
今まで実行ファイル内のphi.soという説明をしていましたが、実際には
一旦一時ファイルとして出力し、それをリンクしています。そのファイル
のファイル名が一時ファイル名。(exe???.tmp)

2. 拡張ライブラリをrequireするたびに、phi.soというファイルを
リンクしていないかどうか調べる。
もしリンクしていたら、先ほど保存した一時ファイル名に置換する。

こんな感じの処理をしています。そう、Apolloのためだけに。(笑)
もちろん、phi.soよりも先にjpeg.soがrequireされると失敗します。
もしphi.soへのリンクが無くなれば、以下のようなシンプルな
構成になります。

+-------------+
| Exerb Core | <-+<-+
+-------------+ | |
| Archive | | |
| +---------+ | | |
| | foo.rb | | | |
| +---------+ | | |
| | phi.so ------+ |
| +---------+ | |
| | jpeg.so ---------+
| +---------+ |
+-------------+

こうなれば他の拡張ライブラリと同じなので、特殊な処理は必要ありません。

と、ここまでがApollo第1問題。(と、脳内では呼んでいる)
もう一つ、Apollo第2問題というものがあって、それはファイル名の長さ。
phi.soというファイル名は、非常に短い!(涙)

Exerbのインポートテーブル書き換え処理(リンクのねじ曲げ)では、
インポートテーブルを1から再構成・・・みたいなことはやっていません。
一部のファイル名だけをちょこちょこと書き換える、という手法を
用いています。ええ、我ながらせこいですね。

通常の拡張ライブラリはmswin32-ruby18.dll(18byte)というファイル名
でリンクしているわけですが、Exerbではこの部分を自分自身のファイル名
(例えばfoo.exe)に書き換えることでリンクのねじ曲げを行っています。
バイナリレベルでは foo.exeruby18.dll みたいな感じに上書きされて
いるわけです。よって現在のExerbには実行ファイル名の長さ制限があります。

これがphi.soの場合、exe???.tmpという一時ファイル名に書き換えないと
いけないのですが、

phi.so
exe???.tmp

のように4バイトも領域が足りません。
もちろんExerbはここで諦めたりはしません。インポートテーブルの
未使用領域を探し出して、そこに文字列を埋め込み、インポートテーブル
の文字列の参照先を変更します。
が、この処理が非常に心配なのです。とりあえず動作しているようなの
ですが、作者本人も、どうして動いているのかどうかわかりません。(笑)
できればこの処理を省きたい、と私は思っています。


以上がApollo第1問題、同第2問題の解説です。
我ながら分かりにくい説明ですが、ご理解頂けたでしょうか?

# はぁ、疲れた。(笑)

====== Yuya Kato ======
E-Mail yuya@…
Web http://nuance.cc/
i-mode http://nuance.cc/i/

このエントリーをはてなブックマークに追加
添付:

このメールは下記のメールに対する返信です:

このメールには下記のメールが返信されています:

更新順メールリスト