3

私はMIPS32エミュレーターを作成しており、gccを使用してCプログラムをコンパイルするときに、標準Cライブラリ全体(おそらくGNU拡張機能を使用)を使用できるようにしたいと考えています。

この時点で理解しているように、I/OはMIPS32アーキテクチャ上のシステムコールによって処理されます。libc / glibcを使用してプログラムを正常に実行するには、どのsyscallをエミュレートする必要があるかをどのように判断できますか?(試行錯誤なし)

編集:システムコールの意味の例については、これを参照してください。

(興味があれば、ここでプロジェクトをチェックできます。フィードバックは大歓迎です。非常に初期の段階であることに注意してください)

4

4 に答える 4

6

非常に短い答え

はるかに長い答えを読んでください。

短い答え

エミュレータの一部の機能を使用してホストOSにシステムコールを実行させるカスタムlibcを提供する場合は、それらすべてを実装する必要があります。

はるかに長い答え

少し戻って、実際の(エミュレートされていない)システムで物事が通常どのように階層化されているかを見てください。

  1. 周辺機器にはいくつかのI/Oインターフェイス(番号付きポートやメモリマッピングなど)があり、CPUはそれをくすぐって何でも実行できます。
  2. CPUは、ハードウェアの操作方法を理解するソフトウェアを実行します。これは、単一目的のプログラムでも、他のプログラムを実行するオペレーティングシステムでもかまいません。libcが写真に写っているので、OSがあり、それがUnix-yであると仮定しましょう。
  3. OSによって実行されるユーザースペースプログラムは、OSとの間で定義されたインターフェイスを使用して、特定の「システム」機能の実行を要求します。

あなたが達成しようとしていることは、レイヤー3と2の間で行われ、libcまたはユーザーコードの関数は、OSがシステムコールをトリガーすると定義したものをすべて実行します。これにより、多数のワームの缶が開かれます。

  • OSがシステムコールのトリガーとして定義するものは、OSごとに異なり、(まれに)同じOSのバージョン間でも異なります。この問題は、これらの詳細を非表示にする動的にリンク可能なlibcを提供することにより、「実際の」システムで軽減されます。それはさておき、実行したいMIPS32バイナリがある場合、エミュレータがサポートするシステムコール規則を使用しますか?

  • エミュレータが特定のシステムコールを実行していると認識できることを実行するカスタムlibcを提供する必要があります。実行したいプログラムは、プログラムが必要とする他のライブラリと同様に、MIPS32にクロスコンパイルし、静的にリンクする必要があります(libmが思い浮かびます)。または、エミュレータパッケージは、動的リンカーのシミュレーションに加えて、必要なすべてのライブラリの動的にリンク可能なコピーを提供する必要があります。これは、ホスト上でライブラリを開くことが機能しないためです。プログラムを最初から再コンパイルするのに十分なソースがある場合は、エミュレーションよりも移植の方が適している可能性があります。

  • 特定のシステム上のファイルへのパスに関する仮定、または特定のデバイス(それ自体がファイル)で検出されるものに関する他の仮定を行うコードは、正しく実行されません。

  • レイヤー2を提供している場合は、オペレーティングシステム全体の特定のバージョンの動作の完全で正しいシミュレーションを提供するためにサインアップしていることになります。いくつかの呼び出しは好きread()で、write()扱いやすいでしょう。他の人はのようfork()に、uselib()そしてioctl()はるかに難しいでしょう。また、プログラムが使用する呼び出しと動作を、ホストOSが提供するものと1対1でマッピングする必要はありません。これはすべて、ホストがUnixであり、ターゲットプログラムもUnixであることを前提としています。ターゲットが他の環境用にコンパイルされている場合、すべての賭けは無効になります。

最後のポイントは、ほとんどのエミュレーターがCPUと一部のターゲットシステム(つまり、レイヤー1のすべて)のハードウェア動作のみを提供する理由です。これらを配置すると、元のシステムのブートROM、OS、およびユーザープログラムをすべて変更せずに実行できます。これを実行し、エミュレートするハードウェア上で実行されたオペレーティングシステムの変更されていないバージョンを実行できる既存のMIPS32エミュレーターがいくつかあります。

HTHとあなたのプロジェクトの幸運を祈ります。

于 2011-05-04T15:26:31.807 に答える
0

ISO標準CライブラリのほとんどはストレートCで記述できます。低レベルのOS機能にアクセスする必要があるのはごく一部です。

少なくとも、、、およびのブロックまたは文字レベルで基本的なI/Oをエミュレートする必要がfopenありfreadますfwrite。ただし、Unixのアプローチを採用し、それらを下位レベルの、、、および呼び出しの上に実装することもopenできreadますwrite

また、との動的メモリ割り当てを管理する必要がmallocありますfree

Andsetjmplongjmp、実行スタックへのアクセスが必要です。

またtimesignal.h機能。

于 2011-05-04T15:04:21.557 に答える
0

MIPSがどのように機能するかは正確にはわかりませんが、Win32では、OS呼び出しをDLL/EXEインポートテーブルを介してプロセスに明示的にインポートする必要があります。MIPSシステムで使用される実行可能形式にも同様のものが存在する可能性があります。

于 2011-05-04T15:21:29.240 に答える
0

通常のアプローチは、CPUだけでなく、代表的な標準周辺機器のセットもエミュレートすることです。次に、libcとハードウェアドライバーが含まれているエミュレーターでオペレーティングシステムを起動します。Libcは、エミュレーターの仮想ハードウェアを呼び出すOSesドライバーを呼び出します。一般的な例については、DosBoxを参照してください。

あなたの質問の他の解釈は、完全なエミュレーターを書きたくないということですが、mips32以外のシステムでmips32バイナリーを実行できるようにするバイナリー互換性レイヤーです。その人気のある例は、PowerPCアプリケーションも実行できるMacOsX(Intel)です。

後者のシナリオでは、OSes ABI(アプリケーションバイナリインターフェイス)をエミュレートする必要があります。または、libcのABIを使用することもできます。どちらの場合も、エミュレータで実行されるスタブコードと、ホストで実行されるプロキシコードを実装する必要があります。

  • スタブは関数呼び出し引数をシリアル化します
  • ...そして、いくつかの特別な仮想命令を使用して、エミュレータメモリからホストメモリにそれらを送信します
  • プロキシは引数(エンディアン、整数長、アドレス空間など)にパッチを適用する必要があります
  • ...そしてホストシステムで関数呼び出しを実行します
  • 次に、プロキシは出力関数の引数をペーシングしてシリアル化します
  • ...そしてそれらをスタブに送り返します
  • ...データを発信者に返します

ほとんどの呼び出しは汎用スタブ/プロキシでは機能しませんが、特定のソリューションが必要です。

幸運を!

于 2011-05-04T15:36:14.023 に答える