web-dev-qa-db-ja.com

Mac OS XとLinux間のバイナリ互換性

自分を大事にしてください。この質問は、私がUNIXのようなシステムの内部の仕組みやプログラミング全般に比較的慣れているので、素朴で馬鹿げているように見えるでしょう。

準備はいい? OK! 3つのレベルの滑稽さを経験し、進むにつれて増加します。


1つは実行中(ここにLinuxディストリビューションを挿入:今後はUbuntuが使用されます)、もう1つは実行中、Mac OS Xとしましょう。

1つは同等のプログラムをコンパイルします。

int main()
{
    int cat = 33;
    int dog = 5*cat;
    return dog;
}

共有ライブラリの影響をまだ考慮したくないので、コードは非常に単純です。

それぞれのシステムでコンパイルした場合。出力の主な違いはELFとMach-Oの問題ではありませんか?フォーマットの各バイナリを取り除き、フラットバイナリを残した場合、逆アセンブルされた機械語命令は同じではないでしょうか? (おそらくコンパイラの習慣/傾向に応じていくつかの違いがあります)。

1.) Ubuntuシステムから生成されたフラットバイナリをMach-Oフォーマットで再パッケージするプログラムを開発した場合、それはMac OS Xシステムで実行できますか?次に、上記の想定プログラムのコンパイル済みバイナリのみがあり、フラットバイナリを再パッケージするためのこの神秘的なツールがあった場合、単純なプログラムをMac OS Xシステムで実行できますか?


これで、次のようなソースを持つプログラムができました。

#include <stdio.h>
int main()
{
    printf("I like tortoises, but not porpoises");
    return 0;
}

2.)このプログラムがコンパイルされて静的にリンクされていると仮定すると、魔法のプログラムは未加工のバイナリをMach-O形式で再パッケージ化してMac OS Xで動作させることができますか?他のバイナリに依存する必要がないように見える(この場合、Macシステムにはない)


3.)この想定されるプログラムを使用して、必要なすべての共有ライブラリをMach-O形式に変換し、代わりに上記のプログラムを動的リンクを使用してコンパイルした場合はどうなるでしょうか。プログラムは引き続き実行されますか?

それは今のところそれであるはずです、明らかに不合理の各ステップは意味をなすために前のベースに依存しています。したがって、最初の柱が破壊された場合、残りの層に多くのメリットがあるとは思えません。

GUIを念頭に置いたプログラムでは、これについては考えさえしません。ウィンドウシステムはおそらく他の頭痛の種になるでしょう。この段階では、コマンドラインプログラムのみを検討しています。

今、私は世界に私を是正するように誘い、私の不条理な考え方に問題があることをすべて教えてくれます。

28
zec

重要なことを1つ忘れてしまいます。つまり、興味深いことを行うには、プログラムがオペレーティングシステムと対話する必要があります。

LinuxとOS Xでは規約が異なるため、オペレーティングシステムに依存するコードのチャンクを操作しなければ、同じバイナリをそのまま実行することはできません。これらの多くはライブラリに隠されているため、リンクする必要があります。つまり、プログラムはリンク可能である必要があり、リンクも2つのシステム間で異なります。

そして、それは何度も続きます。表面的には同じことをしているように聞こえますが、実際の詳細は大きく異なります。

誰かがそれを実現するのに十分な時間を費やしたい場合、これは実行可能です。 ダーリングプロジェクト はこれを試みていますが、これを書いている時点では、かなり原始的な状態です。

他のプラットフォームでは以前に成功しています:

  • SolarisとUnixWareには、 lxrun と呼ばれるヘルパープログラムが含まれています。これは、Sudoのように機能します。実行可能ファイルの名前とパラメーターをヘルパーに渡し、動的に修正します。実行可能ファイルはOSと通信できます。 公式サイト (ダウン、 アーカイブリンク )は、それが bitrotted だと言っています。

  • Linuxのカーネルにはかつて iBCS と呼ばれる機能がありましたが、カーネルは「外部」バイナリを直接認識したのでヘルパーを必要としませんでした。それは カーネル2.3開発シリーズ中に荒廃しました 、おそらく2.4が出てから小さなUnixサーバーの戦いが本質的に終わったためです。

  • FreeBSDのカーネル Linuxバイナリを認識するように設定できます であり、ネイティブであるかのように実行します。この機能は、上記の2つよりも形が良いようです。

    OpenBSDとNetBSDには同様の機能があります。

OS Xには多くのFreeBSDが含まれています なので、Linuxサポートの移植は簡単です。

18
Warren Young

私はだいたいみんなに同意しますが、それを付け加えたいのですが、これにはかなりの時間と労力がかかりますが、Wineを開発するのにかかったほどではありません。

Wine開発における困難の多くは、クローズドソースのオペレーティングシステムからバイナリ形式を移植しており、システムコールの多くが文書化されていないことです。彼らは基本的にオペレーティングシステムをリバースエンジニアリングする必要がありました。

誰かが1つのオープンOSから別のオープンOSにこれを行う場合、同等のネイティブシステムコールがあれば互換レイヤーが他のOSからコピー/貼り付けされる可能性があるため、1/10の時間で完了する可能性があります。存在しません。もちろん、POSIXの世界ではほとんどの場合、ネイティブコールを利用できます。

注目すべきもう1つのプロジェクトはReactOSで、本質的に完全なバイナリ互換バージョンのWindowsを作成しています。Wineは必要ありません。

3
joe

MacOSで技術的に実行可能ですが、かなりの努力が必要ですが、努力の一部はすでに行われています。

  • MacOSと再ブランド化されたRed Hat Enterprise Linuxの両方がUNIX 03として認定されています。これは、原則として、POSIX呼び出しは同じAPIを持つ必要があることを意味します。
  • MacOSとLinuxはどちらもAMD64プラットフォームにSystem V ABIを使用します。つまり、AMD64 macOSとLinuxには互換性のあるABIとAPIが必要です。
  • linuxがELFを使用する一方で、macOSはMach-Oをネイティブ実行可能形式として使用します。実行可能ファイル形式を使用して互換性レイヤーを呼び出す必要があるかどうかを区別できるので、これにより状況が簡単になります。ただし、これにはbinfmt_miscのようなものが必要になります。
  • それを正確に提供するサードパーティのmacOSカーネル拡張が存在します。 ELFをロードするためにmacOSをロードする方法があります。ELFをロードして実行するMach-O実行可能ファイルである特別なld-linux.soが必要です。

ここで必要なのは、少なくとも次のことができる特別なld-linux.soです。

  • Mach-O実行可能ファイルまたはdyld自体であること
  • Linux ELFファイルを正しいアドレスのメモリにロードできます。
  • うまくいけば、Linux sonameをmacOSのものにマッピングし(例/lib/libc.so.6から/lib/libSystem.B.dylib)、一致するELFが見つからない場合に対応するMach-Oをロードできるため、macOSライブラリを再利用できます

ELFの上のローダーで直接システムコールを行わない場合は、動作する可能性が高くなりますが、システムコールを使用したELFは動作しない可能性があります。役立つ可能性のある2番目のコンポーネントは、それらのLinux syscallをキャッチしてmacOSのものにマップするカーネル拡張です。デスクトップの使用に関しては、LinuxグラフィックコールをOpenGL.frameworkおよびMetal.frameworkにマッピングするために、特別なメサ実装が必要です。

1
Maxthon Chan

これが非常に役立つと思われる専門のLinuxアプリがいくつかあります。 FPGA側では、QuartusとVivadoはLinuxで実行されるプログラムの良い例であり、最新のFPGAをターゲットとするソースコードや同様のプログラムが利用できる可能性はほとんどありません。

私はあなたの質問への簡単な答えは、ソースがあるMacOSで再コンパイルし、時間がある場合に機能を提供するグループを形成することです-そしてそれは時間のかかる作業になります。

0
Daniel Wisehart