2009-02-26 11 views
1

私はELF形式の理解をあきらめたので、自分の言語用の小さなプログラムローダーを書いています。私はメモリ上のファイルをmmapして何かを歓迎します。グローバルオフセットテーブル(GOT)を自分の言語でx86に渡すのに最適な方法を教えてください。

私はプログラムの共有を妨害したくはありません。したがって、私はCとelfと同じことをします:グローバルオフセットテーブル。

問題は次のとおりです。私のプログラムにGOTを渡すにはどうすればいいですか?

最初に気になることは、レジスタまたはスタックの引数でそれを与えることです。レジスタでは素晴らしいはずですが、x86はレジスタの数によって遅くなります。これは、私がebxやebpなどを失うことを意味する可能性があります。合理的なアーキテクチャでは、これは公正なトレードオフになります。 x86では少し失敗しているようです。

共有ライブラリを逆アセンブルすると、gccがIP相対アドレッシングとして実行していることがわかります。もし私がこれをしたら、それは次のようになります:

call 0 
here: 
    pop eax 
    ; do something with [eax + (got - here) + index*4] 

しかし、これは部分的には複雑です。私はこれをすることについて好きではありません。

これ以上のアイデアはありますか?

編集:複数のライブラリでこれを処理するために取得する場合、私はこれを実現:私はアプリごとに複数のGOTSを持つことになりますし、特定のGOTを使用すると、私は思います、コードのどのチャンクに依存ので、別でGOTを維持します。私が気付いていないいくつかの追加のトリックが必要になります。私は彼らがレジスタにGOTを保持するときにこの問題を解決する方法を知りたいと思います。

答えて

1

バイナリイメージのベースにセグメントレジスタ(またはそのベース)の1つを使用できます。だからあなたはあなたのグローバルデータを参照するでしょう。 FS:xxxとして

これらのレジスタは、いわゆるセグメント化メモリモデルの残りの部分です。基本的に、セグメントは、指定されたベース(およびリミット)を持つリニアアドレス空間への "ウィンドウ"であり、アドレッシングに使用する場合(たとえば、アドレスが0010:00000001の場合)、結果のアドレスは(セレクタ0010 )+00000001。セグメントのベース(およびその他のパラメータ)は、メモリ内の特別な領域であるディスクリプタ・テーブル(これらの中にさらに多くがある)に格納されます。これらはカーネルモードでしか変更できません。これを行うlinuxのシステムコールがあります(modify_ldtarch_prctl)。 64ビットモードでは、状況はもう少し複雑です。

参考のため、AMD64 architecture manual、特に第2巻:システムプログラミングを参照してください。

+0

私はこれらのセグメントレジスタについて読む必要があります。これまで私はそれらを遺産として無視してきました。 – Cheery

+0

実際には、GSおよびFSは64ビットモードで使用できます。フラットアドレッシングモードの例外です。 –

関連する問題