2

私はJavaプログラマーですが、Cでやるべきことはほとんどありません。そこで、以下のような簡単な例から始めました。コンパイルして実行可能ファイル(hello)を生成した場合、元のファイル(hello.c)を使用せずに任意のUNIXプラットフォームで実行可能ファイル(hello)を実行できますか?また、実行可能ファイルからデータを読み取る方法はありますか?実行可能ファイルを元のファイル(hello.c)に逆コンパイルしますか?

[oracle@oracleapps test]$ cat hello.c
#include <stdio.h>
int main(){
int i,data =0;
for(i=1;i<=64;i+=1){
data = i*2;
printf("data=%d\n",data);
}
return 0;
}

コンパイルする

gcc -Wall -W -Werror hello.c -o hello
4

6 に答える 6

2

結果の実行可能ファイルは、実行可能ファイルをコンパイルしたプラットフォームとABI互換のプラットフォームで実行できます。ABI互換性とは、基本的に、同じ物理プロセッサアーキテクチャとOSインターフェイス(および呼び出し規約)が2つの(場合によっては異なる)OSで使用されることを意味します。たとえば、FreeBSDにはLinux ABI互換性が含まれているため、FreeBSDシステム(同じプロセッサタイプ)でLinux用にコンパイルされたバイナリを実行できます。ただし、ハッカリーが行われない限り、他のすべてのタイプのユニスでバイナリを実行できない場合があります。たとえば、LinuxでMac OS Xアプリケーションを実行することはできませんが、この人はLinuxでいくつかのOS Xコマンドラインツール(GCCコンパイラ自体を含む)を使用できるソリューションを持っています。

リバースエンジニアリング:マシンコードからCコードを生成することを目的とした逆コンパイラーは確かにありますが、(まだ)それほど強力ではありません。この理由は、それらが本質的に書くのが非常に難しいからです。マシンコードパターンを認識する必要がありますが、それでも元の情報をすべて収集することはできません。たとえば、ループのタイプ、コメント、非静的ローカル変数名、およびほとんどのタイプは、コンパイルプロセス中にすべて失われます。たとえば、次のようなCソースファイルがある場合:

int main(int argc, char **argv)
{
    int i;
    for (i = 0; i < 10; i++)
    {
        printf("I is: %d\n", i); /* Write the value of I */
    }

    return 0;
}

C逆コンパイラーは、次のコードを再構築できる場合があります。

int main(int _var1, void *_var2)
{
    int _var3 = 0;
    while (_var3 < 10)
    {
        printf("I is: %d\n", _var3);
        _var3 = _var3 + 1;
    }

    return 0;
}

しかし、これはこのようなかなり高度な逆コンパイラーになります

于 2012-08-12T17:26:57.923 に答える
1

いいえ...各プラットフォームには、異なる実行可能フォーマット要件、異なるハードウェアアーキテクチャ、リンカーによって決定される異なる実行可能メモリレイアウトなどがあります。コンパイルされた実行可能ファイルは、他のプラットフォームではなく、現在コンパイルされているプラ​​ットフォームに「ネイティブ」です。ただし、現在のマシンで別のアーキテクチャ用にクロスコンパイルすることはできます。

たとえば、多くの類似点がある場合でも、Linux x86でコンパイルされた実行可能ファイルは、そのフレーバーによってはBSDでの実行が保証されません(つまり、FreeBSDで実行できる可能性がありますが、通常、OSXのDarwinバージョンのBSDでは両方を考慮していません。マシンは同じ基礎となるハードウェアアーキテクチャを持っているかもしれません)。また、IRIXを実行しているSGI MIPSマシンで何かをコンパイルして、Solarisを実行しているSunSPARCで実行することもできませんでした。

于 2012-08-12T17:18:34.367 に答える
1

どのプラットフォームでも実行可能ファイルを実行することはできません。

実行可能ファイルは、.cファイルなしで他のマシン(またはこのマシン)で実行できます。同じハードウェアで実行されている同じOS/ディストリビューションの場合。

デコンパイラーを使用して逆アセンブラーを使用してファイルを読み取り、アセンブリーまたはCとして表示できます。元のcファイルとはあまり似ていません。

于 2012-08-12T17:19:41.437 に答える
1

コンパイルされたファイルは純粋なマシンコード(およびいくつかのメタデータ)であるため、ソースファイルが存在する必要がないという点で自給自足です。欠点は?マシンコードはOSとプラットフォームの両方に固有です。プラットフォームとは、通常、CPUの命令セット、つまり「x86」または「PowerPC」を意味しますが、特定のコンパイラフラグを使用してコンパイルされたコードの中には、特定の命令セット拡張が必要な​​場合があります。OSの依存関係は、実行可能ファイルの形式の違い(PEではなくELFなど)だけでなく、OS固有のサービスまたはOS固有の方法での一般的なOSサービス(システムコールなど)の使用によっても発生します。それに加えて、ほとんどすべての重要なコードはいくつかのライブラリ(少なくともCランタイムライブラリ)に依存しているので、おそらくあなたはそうするでしょう 互換性のあるバージョンで適切なライブラリがなくても実行可能ファイルを実行することはできません。したがって、実行可能ファイルは10年前のプロプライエタリUNIXでは実行されない可能性があります。異なるLinuxディストリビューションでは実行されない場合があります(ただし、プログラムに依存している可能性が高いため、実行される可能性は十分にありますglibc)。

マシンコードは簡単に分解できますが、結果は非常に低レベルであり、多くの人にとって役に立たないものです。Cへの逆コンパイルは、試みはありますが、ほとんどの場合、はるかに困難です。アルゴリズムは、何らかの方法でマシンコードにエンコードする必要があるという理由だけで、回復できます。デバッグ用にコンパイルしなかったとすると、コメント、フォーマット、変数名などは復元されないため、「完璧な」逆コンパイラーでも、入力したものとは異なるCファイルが生成されます。

于 2012-08-12T17:22:30.717 に答える
0

はい、どのUNIXで実行しても実行できますqemu。これは、jvmが実行されている任意のUNIXで実行できるJavaプログラムにかなり匹敵します...

于 2012-08-12T17:42:04.143 に答える
0

Cプログラムでは、プログラムはコンパイルされた環境に関連付けられています(クロスコンパイルしない限り、通常はコンパイルされたプラットフォームと同じです)。あるバージョンのLinux(および特定のハードウェアアーキテクチャ)用に構築されたものを、同じバージョンのLinuxを実行している同じアーキテクチャの別のマシンにコピーすることができます。多くの場合、関連するバージョンのLinuxで実行することで問題を回避できます。ただし、x86 / 64コードをIA32マシン、PPCマシン、またはSPARCマシンで実行することはできません。基本的なO/Sが十分に類似している場合は、IA32コードをx86/64マシンで実行できる可能性があります。また、Debian用にコンパイルされたものをRedHatで実行したり、その逆を実行したりできる場合とできない場合があります。プログラムが使用するライブラリによって異なります。

Javaは、コンパイルされるプラットフォームに依存しないバイトコードプログラムと、各プラットフォームで実行するプラットフォーム固有のJVM(JRE)を用意することで、これを回避します。このWORM(Write Once、Run Many)の動作は、Javaの重要なセールスポイントでした。

于 2012-08-12T17:21:03.790 に答える