1

私のpythonデバッガーには、文字列をファイル名に再マッピングする方法があります。これにより、デバッガー内でexec'd関数をステップスルーするときに、pygmentized行をリストしたり、realgudを介してEmacsなどのエディター内でそれらを表示したりできます。

そのため、CPython が評価中に停止したときに、exec ステートメントで文字列を抽出できるようにしたいと考えています。

呼び出し元が であったEXEC_STMTかどうかを確認するために呼び出しフレームを振り返ることができるメカニズムが既にあり、前の命令が say であったかどうかを確認するために 1 つの命令を振り返ることができますDUP_TOP。したがって、呼び出し時にスタック エントリを読み取る方法を見つけて、文字列を評価することができれば、私は家にいることができます。これを取得するために C にドロップする方法はおそらくありますが、CPython の内部構造に関する私の知識が不足しているため、これを行うことは避けたいと考えています。そこにパッケージがある場合は、オプションで含めることができます。

CPython はすでに関数の引数とローカル変数へのアクセスを提供していますが、もちろんこれは組み込み関数であるため、関数のパラメーターとして記録されません。

同じことを行う方法について別の考えがあれば、それも問題ありません。execデバッガーはゲームの後半に持ち込まれる可能性があるため、どういうわけかオーバーロードまたは置換を試みることは、あまり良い解決策ではないと思います。

ここでは、CPython2 と CPython3 が少し異なる可能性があることは理解していますが、最初はどちらでも構いません。

4

2 に答える 2

0

私は今、道を見つけたと思います。

デバッガー内で、コール スタックを 1 レベル上に移動してexecステートメントに到達します。次に、 uncompyle6を使用してソース コードの構文ツリーを取得します。(これを簡単にするために、uncompyle6 で変更が必要になる場合があります。)

呼び出し時点のツリーには、 のようなものがありexec_stmt -> expr ...ます。その式には、必ずしも式の値ではない式のテキストが含まれます。式は定数の文字列値である場合もありますが、 のような複雑なものである場合もあります"foo" + var1

そのため、デバッガーは、呼び出しスタックの式を評価する方法を知っているデバッガーのコンテキストでその文字列を評価できます。

これには、式を再評価すると副作用が生じる可能性があるという問題がまだあります。しかし、それは悪いプログラミング手法ですよね? ;-)

代わりに、ソースが存在しない場合は、バイトコードからコードを逆コンパイルするだけです。これには、バイトコードで言及されている行番号がバイトコード内の行番号と常に一致するとは限らないという欠点があります。そのためには、上記の文字列を再作成する方法が優れています。

最後に、なぜ本当に優れたデバッガーを作成するのが難しいのか、また、現在停止している時点でソース テキストを取得するなどの単純なことでさえ、膨大な数のデバッガーに多くの制限がある理由を説明したいと思います。

まったく異なるアプローチは、早期に停止して、スタックにアクセスできるbyterun (または適切に変更された Python C モジュール) などのサブインタープリターに切り替えることです。

于 2016-05-02T08:39:39.493 に答える