6

私はエミュレーターが何をするのかを理解しており、ある機械語を別の機械語に変更します。多くの場合、「ジャストインタイム」です。あるアーキテクチャ用に作成されたバイナリを読み取り、別のアーキテクチャ用に新しいバイナリを保存するようなプログラムを組み込むことができますか。プロセスが完了すると、指定されたアーキテクチャでネイティブに実行できるバイナリがユーザーに残されます。これは、レガシーアーキテクチャ用の高価なプロプライエタリアプリケーションを持っている人にとって特に便利です。

そのような申請をすることは可能ですか?バイナリリコンパイルは新しい概念ではありませんが、そのような有用な実装はまだ見つかりません。

他の人の助けを借りて、そのようなプログラムのプログラミングが可能であれば、そのようなプログラムのオープンソース実装でコーディングを開始することにワクワクします。

4

3 に答える 3

8

静的再コンパイルは、バイナリを外部アーキテクチャから別のターゲット アーキテクチャに変換する有望な方法です。実行直前にコードをコンパイルする必要がなく、余分なコンパイル時間が生成コードの最適化に役立つため、ジャストインタイム (JIT) よりも高速です。

ただし、JIT コンパイルは動的プログラム分析を使用しますが、静的再コンパイルは静的プログラム分析に依存します (名前の由来)。

静的分析では、実行に関するランタイム情報はありません。

これに関する主な問題は、間接的なジャンプによって引き起こされます。switchこの用語は、特定のステートメント、関数ポインターの使用、またはランタイム ポリモーフィズム (仮想テーブルを考えてください) から生成される可能性のあるコードを対象としています。それはすべて、次の形式の命令に要約されます。

JMP reg_A 

プログラムの開始アドレスを知っていて、この時点から命令の再コンパイルを開始することにしたとします。ダイレクト ジャンプに遭遇すると、そのターゲット アドレスに移動し、そこから再コンパイルを続行します。ただし、間接ジャンプに遭遇すると、行き詰まります。このアセンブリ命令では、 の内容はreg_A静的にはわかりません。したがって、次の命令のアドレスはわかりません。動的再コンパイルでは、レジスタの仮想状態をエミュレートし、 の現在の内容がわかっているため、この問題は発生しないことに注意してくださいreg_Aその上、静的再コンパイルでは、すべての可能な値を見つけることに興味がありますreg_Aこの時点で、考えられるすべてのパスをコンパイルする必要があるためです。動的分析では、現在実行しているパスを生成するために現在の値のみが必要です。reg_Aその値を変更する必要があります。他のパスを生成することはできます。場合によっては、静的分析で候補のリストを見つけることができます (その場合switch、可能性のあるオフセットのテーブルがどこかにあるはずです) が、一般的なケースではわかりません。

それでは、すべての命令をバイナリに再コンパイルしましょう!

ここでの問題は、ほとんどのバイナリにコードとデータの両方が含まれていることです。アーキテクチャによっては、どれがどれか分からない場合があります。

さらに悪いことに、一部のアーキテクチャでは、アライメントの制約や可変幅の命令がなく、ある時点で逆アセンブルを開始すると、オフセットを使用して再コンパイルを開始したことに気付く場合があります。

2 つの命令と 1 つのレジスタで構成される単純化された命令セットを見てみましょうA

41 xx (size 2): Add xx to `A`.
42 (size 1): Increment `A` by one.

次のバイナリプログラムを考えてみましょう:

41 42

開始点が最初のバイトだとしましょう41。あなたがやる:

 41 42 (size 2): Add 42 to `A`.

しかし、41 が 1 つのデータである場合はどうなるでしょうか。次に、プログラムは次のようになります。

 42 (size 1): Increment `A` by one.

この問題は、多くの場合、アセンブリで直接最適化された古いゲームで拡大され、プログラマーは、コンテキストに応じて、一部のバイトがコードとデータの両方として解釈されることを意図的に期待する可能性があります!

さらに悪いことに、再コンパイルされたプログラム自体がコードを生成している可能性があります。JIT コンパイラーの再コンパイルを想像してみてください。その結果、ソース アーキテクチャのコードが出力され、そこにジャンプしようとするため、プログラムがすぐに停止してしまう可能性が高くなります。実行時にのみ利用可能なコードを静的に再コンパイルするには、無限の策略が必要です!

静的バイナリ解析は非常に活発な研究分野 (主にセキュリティの分野で、ソースが利用できないシステムの脆弱性を探すため) であり、実際に私は、プログラムを静的に再コンパイルしようとする NES エミュレーターを作成しようとする試みを知っています。記事はとても興味深いです。

JIT と静的再コンパイルの間の妥協点は、静的に変換できないビットのみを保持して、できるだけ多くのコードを静的に再コンパイルすることです。

于 2015-08-25T11:32:28.430 に答える
3

静的な再コンパイルと動的な再コンパイルを探していると思います。動的再コンパイルは、「リアルタイム」エミュレーションまたは再コンパイルと呼ばれるものです。コードはブロック単位で再コンパイルされるため、エミュレーターは元のコードのランタイム環境を正確に反映できます。

静的な再コンパイルは、可能かどうかを尋ねているものです。一部の人が指摘しているように、さまざまな状況で可能ですが、非常に具体的な実行時の制約を期待するコードは、静的な再コンパイル後に正常に実行されない場合があります。これが、静的再コンパイルを使用する N64 エミュレーターである Corn が、高度に手作業で最適化されたごく少数のゲームしか実行できないのに対し、動的再コンパイルを使用する他の N64 エミュレーターは、はるかに幅広い種類のゲームを実行する理由です。

静的な再コンパイルは、さらに複雑で従来のコード (x86 から PowerPC へ) に対しても可能ですが、再コンパイラーは、生成された静的コードをターゲット上で確実に実行するために多くのトリックを使用する必要があるため、非常に面倒です。機械。動的再コンパイラーは、開発作業のほんの一部で実行時にオンザフライでこれを行うことができ、パフォーマンスのコストはごくわずかです。

于 2012-06-26T21:29:29.770 に答える
0

参照されているライブラリもこれを使用して再コンパイルされていることを確認することから始めなければなりません。

可能ですが、大事業です。

また、これを行うことでライセンスの問題が発生する可能性があることも考慮してください。元のソフトウェアに基づいて派生物を作成しています。これを許可するほとんどのライセンスでは、ソースも取得できるため、ソースを再コンパイルまたは移植するだけで済みます。これははるかに簡単です。

于 2012-06-26T20:51:51.167 に答える