2016年7月9日土曜日

D言語ローレイヤ入門

D言語(ローレイヤ)入門していきます。

ぼく「D言語の最小ランタイムほしいよ~」
ぼく「uefi-dとか使ってみたけど構造体宣言できないし色々ダメ」
ぼく「UEFI AppをDでつくりたい、あわよくば・・・OSカーネルも」

というつぶやきをしたらプロから返事が帰ってきた。
Twitterつよい。


というわけで、minimal.zipを落として makeしてみた

minimal-d/object.d:1248: `_deh_beg' に対する定義されていない参照です
minimal-d/object.d:1249: `_deh_end' に対する定義されていない参照です
無いってさ!
ちなみに、object.dの1248行目と1249行目はこんな感じ。

        extern __gshared
        {
            /* Symbols created by the compiler and inserted into the object file
             * that 'bracket' the __deh_eh segment
             */
            void* _deh_beg;
            void* _deh_end;
        }

※object.d:すべてのクラスや構造体のベースになるクラスが入ったファイル。これがないとD言語の機能はもちろん、C言語で普通にできてた構造体の宣言すらできない(RTTI:実行時型情報が必須な言語の宿命(TypeInfo_Struct等が宣言されてないとリンカエラー))ので、大事。


見たとおり外部に宣言してある_deh_begと_deh_endを参照する ってな感じになってるし
もちろんコンパイラはそんなシンボルを生成してくれないしで、きっとD言語の仕様が微妙に変わったのかもしれない。

リンカスクリプトでEHテーブルセクションを定義した時にシンボルも定義すれば良いんだけど、それをやらなくてもできる方法があるので今回はそっちでやる。
ちなみに、EHテーブルセクション(セグメント)については、ここに書いてあった。
http://www.kmonos.net/alang/d/abi.html

例外ハンドラがたくさん書いてあるところ(GOTみたいな関数テーブル)っていう感じ。

先ず、CompilerDSOData構造体と_d_dso_registryって関数をみてみると
CompilerDSOData構造体には、_deh_beg、_deh_endの2つが居るけど
でもその構造体を引数にとってる、_d_dso_registry関数はそれらメンバに対して何も操作してない。
でも、引数をとってるからには、何かが入ってるはずなので、下のソースみたいに
もともと有った外部参照するところをコメントアウトする。
次に、普通にコメントアウトした変数と同名の変数の実体を宣言する。
さらに、宣言した変数に引数からもらった CompilerDSOData構造体の同名の変数の値を代入する。

これでリンカエラーは出なくなる。

じゃあ本当に直した部分は動くの?動きそうなの?
と言う疑問が湧いてきたので、一旦これでmakeコマンド叩いてみて、バイナリを生成して逆アセンブルしてみる。

動きそう、動かなそうの判断は、意図したデータ(EHテーブルセクションの開始位置と終了位置)
が入ってるか入ってないかで判断する。

各メモリアドレスの詳細


一応メモリアドレスがちゃんと有効なセクションを指してるのと、
構造体の順番と同じようにスタックにレイアウトされてるから問題なさそう。

C言語っぽい擬似コード




てわけで、きょうはこんなところで。

0 件のコメント:

コメントを投稿