質問: linuxの「フレーバー」でコンパイルされたlinux実行可能ファイルは、別のlinuxで実行されますか? linuxの1つのフレーバーでコンパイルされた、次に示すような非常にシンプルなプログラムの実行可能ファイルは、別のフレーバーで実行されますか?それとも再コンパイルする必要がありますか?このような場合、マシンアーキテクチャは重要ですか?int main() { return (99); }
回答: 場合によります。 ia-32(インテル32ビット)用にコンパイルされたものは、amd64で実行できます。これは、intel上のlinuxが(適切なソフトウェアがインストールされた)32ビットアプリケーションとの下位互換性を保持しているためです。 redhat 7.3 32ビットシステム(2002年頃、gccバージョン2.96)でコンパイルしたcodeと、バイナリがcentos 7.4 64ビットシステムにコピーされて実行されます(2017年頃)。-bash-4.2$ file code code: elf 32-bit lsb executable, intel 80386, version 1 (sysv), dynamically linked (uses shared libs), for gnu/linux 2.2.5, not stripped -bash-4.2$ ./code -bash: ./code: /lib/ld-linux.so.2: bad elf interpreter: no such file or directory -bash-4.2$ sudo yum -y install glibc.i686 ... -bash-4.2$ ./code ; echo $? 99 古代redhat 7.3からcentos 7.4(基本的にはredhat enterprise linux 7.4)は同じ「ディストリビューション」ファミリーに留まっているため、2002年からいくつかのランダムな「ゼロからのlinux」インストールから2018年に他のランダムなlinuxディストリビューションに移行するよりも移植性が高い。amd64用にコンパイルされたものは、linuxの32ビットのみのリリースでは動作しません(古いハードウェアは新しいハードウェアを認識しません)。ライブラリや システムコールでも は下位互換性がない可能性があるため、コンパイルのトリックや古いコンパイラの入手が必要になる可能性があるため、これは現代のシステムでコンパイルされた新しいソフトウェアにも当てはまります。など、またはおそらく代わりに古いシステムでコンパイルします。 (これは、古代の古いものの仮想マシンを維持するための正当な理由です。)アーキテクチャは重要です。 amd64(またはia-32)はarmまたはmipsとは大きく異なります。そのため、これらの1つからのバイナリが別のバイナリで実行されることは想定されていません。アセンブリレベルでは、main ia-32上のコードのセクションは、gcc -s code.cを介してコンパイルされ、main: pushl %ebp movl %esp,%ebp movl $99,%eax popl %ebp ret amd64システムが処理できるもの(linuxシステムでは、amd64とは対照的にopenbsdは32ビットバイナリをサポートしていません;古いアーキテクチャとの下位互換性 cve-2014-8866 や友人など、攻撃者に余裕を与えます。一方、 ビッグエンディアンmipsシステム mainでは、代わりに次のようにコンパイルされます。main: .frame $fp,8,$31 .mask 0x40000000,-4 .fmask 0x00000000,0 .set noreorder .set nomacro addiu $sp,$sp,-8 sw $fp,4($sp) move $fp,$sp li $2,99 move $sp,$fp lw $fp,4($sp) addiu $sp,$sp,8 j $31 nop intelプロセッサは何をどうすればいいのか分からず、mips上のintelアセンブリについても同様です。qemuまたは他のエミュレーターを使用して外部コードを実行する可能性があります(おそらく非常に遅くなります)。しかしながら!あなたのコードは非常に単純なコードなので、何よりも移植性の問題が少なくなります。プログラムは通常、時間とともに変化するライブラリ(glibc、opensslなど)を使用します。それらのために、さまざまなライブラリの古いバージョンをインストールする必要があるかもしれません(たとえば、redhatは通常、そのようなパッケージ名のどこかに「compat」を置きます)compat-glibc.x86_64 1:2.12-4.el7.centos あるいは、glibcを使用する古い方法のabi変更(アプリケーションバイナリインターフェース)、または最近のc++ 11またはその他のc++リリースによる変更について心配する必要があります。古いバイナリがこれを実行したかどうかは、古いlinuxディストリビューションがほとんどすべてを動的にコンパイルしているか(redhat:はい)かどうかに依存しますが、静的(ディスク上のバイナリサイズを大幅に増やす)をコンパイルしてライブラリの問題を回避することもできます。一方、patchelfのようなものは、動的(elf、ただしおそらくa.out形式ではない)バイナリを再調整して他のライブラリを使用できます。しかしながら!プログラムを実行できることと、実際にそれを使用して何か有用なことを行うことです。古い32ビットintelバイナリは、恐ろしい、バックポートされていないセキュリティ問題があるopensslのバージョンに依存している場合、またはプログラムが最新のwebサーバーとまったく交渉できない場合があります(最新のものとして)サーバーが古いプログラムの古いプロトコルと暗号を拒否する)、またはsshプロトコルバージョン1がサポートされなくなった、または...