Linuxのあるフレーバーでコンパイルされた、以下に示すような小さくて非常に単純なプログラムの実行可能ファイルは、別のフレーバーで実行されますか?または、再コンパイルする必要がありますか?
このような場合、マシンアーキテクチャは重要ですか?
int main()
{
return (99);
}
承認された回答:
場合によります。 Linux on Intelは32ビットアプリケーション(適切なソフトウェアがインストールされている)との下位互換性を維持しているため、IA-32(Intel 32ビット)用にコンパイルされたものがamd64で実行される場合があります。これがあなたのコードコード>です RedHat 7.3 32ビットシステム(2002年頃、gccバージョン2.96)でコンパイルされ、バイナリが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
Ancient RedHat7.3からCentos7.4(基本的にはRedHat Enterprise Linux 7.4)は同じ「ディストリビューション」ファミリーにとどまっているため、2002年のランダムな「LinuxfromScratch」インストールから2018年のその他のランダムなLinuxディストリビューションに移行するよりも移植性が高い可能性があります。 。
amd64用にコンパイルされたものは、32ビットのみのリリースのLinuxでは実行されません(古いハードウェアは新しいハードウェアを認識しません)。これは、古い古いもので実行することを目的とした最新のシステムでコンパイルされた新しいソフトウェアにも当てはまります。ライブラリやシステムコールでさえ後方移植性がない可能性があるため、コンパイルのトリックや古いコンパイラの入手などが必要になる場合があります。古いシステムでコンパイルします。 (これは、古代の古いものの仮想マシンを維持するのに十分な理由です。)
アーキテクチャは重要です。 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
ではありません format)他のライブラリを使用するためのバイナリ。
でも!プログラムを実行できることと、実際にそれを使って何か役立つことをすることは別のことです。古い32ビットIntelバイナリは、バックポートされていない恐ろしいセキュリティ問題が含まれているOpenSSLのバージョンに依存している場合、またはプログラムが最新のWebサーバーとまったくネゴシエートできない場合(最新のように)、セキュリティの問題が発生する可能性があります。サーバーが古いプロトコルと古いプログラムの暗号を拒否する)、またはSSHプロトコルバージョン1がサポートされなくなった、または…