インターネットを検索しましたが、逆コンパイラが元のソース コードを生成できない理由について具体的な答えは見つかりませんでした。満足のいく答えは得られません。どこかで停止問題に似ていると書かれていましたが、その方法はわかりません。では、完璧な逆コンパイラを作成する際の理論的および技術的な制限は何ですか。
4 に答える
これは、非常に簡単に言えば、多対 1 の問題です。たとえば、C では次のようになります。
b++;
と
b+=1;
と
b = b + 1;
コンパイラとオプティマイザが完了すると、すべてが同じ操作セットにコンパイルされる可能性があります。物事を並べ替え、効果のない操作を削除し、コードのセクション全体を書き直します。それが完了するまでに、あなたが何を書いたのかはわかりません。raw-CPU (または vCPU) レベルで、あなたが何をしようとしているのかがよくわかります。
必要のない変数を削除するのに十分スマートです。
{
a=5;
b=func();
c=a+b;
d=func2(c);
}
## gets rewritten as:
REGISTERA=func()
REGISTERA+=5
return(func2(REGISTERA))
まず第一に、プログラムのコンパイル時に変数名が保持されることはありません。...したがって、再構成されたプログラム全体で意味のない変数名を使用することが最善の方法です。コンパイルは通常、一方向ハッシュ関数のような一方向変換です。ハッシュと同様に、同じ値にハッシュできる別のものを生成することは可能かもしれませんが、逆コンパイルされたプログラムが元のプログラムとまったく同じになる可能性はほとんどありません。
コンパイラは情報を捨てます。ソース コードにあるすべての情報がコンパイルされたコードにあるわけではありません。たとえば、コンパイルされた Java では、情報がコンパイラによってのみ使用されるため、パラメーター化されたジェネリック型とパラメーター化されていないジェネリック型の違いを見分けることはできません。一部の注釈はコンパイル時にのみ使用され、コンパイルされた出力には含まれません。これは、逆コンパイルによってある種のソース コードを取得できなかったという意味ではありません。実際のソース コードとは一致せず、情報もありません。
通常、ソース コードとコンパイル済みコードの間に 1 対 1 の対応はありません。本質的に無限の可能性のあるソースが同じオブジェクト コードになる可能性がある場合 (無制限の変数名の長さなどを考えると)、逆コンパイラはどのソースを吐き出すかをどのように推測するのでしょうか?