3

IRコードを静的にスキャンして実行せずに、特定の中間表現のコールグラフを生成するコードを作成しています。IRコード自体はそれほど複雑ではなく、関数呼び出しシーケンスがどのように見えるかをよく理解しているので、必要なのは呼び出しをトレースすることだけです。私は現在それを明白な方法でやっています:

  • 私たちがどこにいるかを追跡する
  • 関数呼び出しに遭遇した場合は、その場所に分岐し、実行して戻ってきます
  • 分岐している間、発信者と着信者の間にエッジを置きます

私は自分が到達しているところに満足していますが、ここで車輪の再発明をしたり、コーナーケースに直面したりしないようにしたいと思います。これを効率的に行う、受け入れられている優れたアルゴリズム(および/またはデザインパターン)があるかどうか疑問に思っていますか?

更新: IRコードは、自作のJavaに似た言語からのバイトコードの逆アセンブルであり、Jasmine仕様のように見えます。

4

2 に答える 2

4

学術的な観点から、いくつかの考慮事項を次に示します。

  • 保守的/正しいことを気にしますか? たとえば、分析しているコードに関数ポインターによる呼び出しが含まれているとします。ドキュメントを生成するだけであれば、これに対処する必要はありません。うまくいかない可能性のあるコードの最適化を行っている場合は、「ポインターを介した呼び出し」が「何でもあり得る」という意味であると想定する必要があります。

  • 例外的な実行パスに注意してください。IR はこれを抽象化する場合としない場合がありますが、多くの操作で言語レベルの例外とハードウェア割り込みの両方がスローされる可能性があることに注意してください。繰り返しますが、後でコール グラフをどうしたいかによって異なります。

  • サイクルをどのように処理するかを検討してください (再帰、相互再帰など)。これは、後でグラフをトラバースするためのコードの書き方に影響を与える可能性があります (つまり、サイクルを永久にトラバースしないようにするために、ある種の「訪問済み」セットが必要になります)。

乾杯。

3月6日更新

元の投稿に追加された追加情報に基づいて:

  • 仮想メソッドの呼び出しには注意してください。一般に、どのメソッドが実行されるかは不明であることに注意してください。呼び出しが特定のクラスのサブクラスのいずれかに行くと想定する必要がある場合があります。標準的な例は次のようArrayList<A>になりますclass B extends A。乱数ジェネレーターに基づいて、 と のインスタンスをリストに追加AしますB。ここで、リスト内のx.foo()すべてを呼び出します。ここで、 は仮想メソッド で、オーバーライドはです。したがって、ソース コードを見るだけでは、実行時にループが、 、または両方を呼び出すかどうかを知る方法はありません。xfoo()ABA.fooB.foo
于 2011-03-06T06:18:41.293 に答える
2

アルゴリズムはわかりませんが、pycallgraphはまともな仕事をします。そのソースを確認する価値があります。長くはないので、既存の設計パターンをチェックするのに適しています。

于 2011-03-06T05:30:21.020 に答える