Pythonヘルパー・スクリプトを使用したネイティブ実行可能ファイルのデバッグ
GDBデバッグに加え、Pythonヘルパー・スクリプトgdb-debughelpers.pyを使用してnative-image
プロセスをデバッグできます。GDB Python APIを使用して、ネイティブ実行可能ファイルまたは共有ライブラリのデバッグに比較的良好なエクスペリエンスが提供されます。Python対応のGDBが必要です。デバッグ拡張はGDB 14.2に対してテストされ、JDK 17以降ではGraalVMで導入された新しいdebuginfo生成をサポートしています。
ノート: gdb-debughelpers.pyファイルは、
gdb
のバージョン14.2より古いバージョンや、GraalVM for JDK 17より古いバージョンでは動作しません。
Pythonスクリプトgdb-debughelpers.pyは、<GRAALVM_HOME>/lib/svm/debugディレクトリにあります。debuginfoの生成が有効になっている場合(デバッグ情報を使用したネイティブ実行可能ファイルのビルドを参照)、スクリプトはビルド・ディレクトリにコピーされます。native-image
ツールはデバッグ情報ファイルにデバッグ・セクション.debug_gdb_scripts
を追加します。これにより、GDBは現在の作業ディレクトリからgdb-debughelpers.pyを自動的にロードします。
セキュリティ上の理由により、GDBは、特定のPythonファイルのロードをリクエストするネイティブ実行可能ファイルまたは共有ライブラリを初めて検出すると、警告を出力します:
warning: File "<CWD>/gdb-debughelpers.py" auto-loading has been declined by your `auto-load safe-path' set to "$debugdir:$datadir/auto-load". To enable execution of this file add add-auto-load-safe-path <CWD>/gdb-debughelpers.py line to your configuration file "<HOME>/.gdbinit". To completely disable this security protection add add-auto-load-safe-path / line to your configuration file "<HOME>/.gdbinit". For more information about this security protection see the "Auto-loading safe path" section in the GDB manual. E.g., run from the shell: info "(gdb)Auto-loading safe path"
これを解決するには、次のように現在の作業ディレクトリを~/.gdbinitに追加します:
echo "add-auto-load-safe-path <CWD>/gdb-debughelpers.py" >> ~/.gdbinit
または、コマンドライン引数としてパスをgdb
に渡します:
gdb -iex "set auto-load safe-path <CWD>/gdb-debughelpers.py" <binary-name>
どちらも、GDBが現在の作業ディレクトリからgdb-debughelpers.pyを自動ロードできるようにします。
スクリプトをGDBに提供するには、自動ロードをお薦めします。ただし、次のようにして、GDBからスクリプトを明示的にロードできます:
(gdb) source gdb-debughelpers.py
プリティ・プリントのサポート
gdb-debughelpers.pyをロードすると、GDBに新しいプリティ・プリンタが登録されます。これにより、ネイティブ実行可能ファイルまたは共有ライブラリをデバッグする際の利便性がさらに高まります。このプリティ・プリンタは、ネイティブ実行可能ファイルまたは共有ライブラリをデバッグするためのJavaオブジェクト、配列、文字列および列挙の出力を処理します。Javaアプリケーションで@CStruct
および@CPointer
注釈を使用してCデータ構造にアクセスする場合、プリティ・プリンタはそれらをJavaデータ構造として出力するように試みます。プリティ・プリンタでCデータ構造を出力できない場合、GDBによって出力が実行されます。
プリティ・プリンタは、ボックス化されたプリミティブ(Javaオブジェクトではなく)のプリミティブ値も出力します。
print
コマンドのp
別名を使用して出力を行うたびに、プリティ・プリンタは、Javaオブジェクトの各ランタイム型への型キャストを実行するためにコールをインターセプトします。これは、p
別名を使用する場合の自動補完にも適用されます。つまり、静的型がランタイム型と異なる場合、print
コマンドでは静的型が使用され、ユーザーはランタイム型を検出して型キャストできます。また、p
別名は、Javaオブジェクトに対するJavaフィールドおよび配列アクセスおよび関数コールを理解します。
制限事項
上書きする方法がないため、print
コマンドは、デフォルトのprint
コマンドの機能を維持しながら、デフォルトの実装を使用します。オーバーライドすると、Java以外のオブジェクトの出力が正しく機能しなくなります。したがって、ユーザーがデフォルトのGDB print
コマンドを引き続き使用できるように、print
コマンドのp
別名のみがプリティ・プリンタによって上書きされます。
プリティ・プリンタの動作を制御するオプション
拡張されたp
別名に加えて、gdb-debughelpers.pyには、プリティ・プリンタの動作をカスタマイズするためのいくつかのGDBパラメータが導入されています。GDBのパラメータは、set <param> <value>
およびshow <param>
コマンドで制御できるため、GDBのカスタマイズ・オプションと統合できます。
-
svm-print on/off
このコマンドを使用して、プリティ・プリンタを有効または無効にします。これにより、print
コマンドの別名p
もデフォルトの動作にリセットされます。または、GDBのprint
コマンドのraw
出力オプションを使用して、プリティ・プリントを抑制できます:
(gdb) show svm-print
The current value of 'svm-print' is "on".
(gdb) print str
$1 = "string"
(gdb) print/r str
$2 = (java.lang.String *) 0x7ffff689d2d0
(gdb) set svm-print off
1 printer disabled
1 of 2 printers enabled
(gdb) print str
$3 = (java.lang.String *) 0x7ffff689d2d0
-
svm-print-string-limit <int>
Java文字列をプリティ・プリントするための最大長をカスタマイズします。デフォルト値は200
です。Java文字列を無制限に出力する場合は、-1
またはunlimited
に設定します。これは、C文字列の上限は変更しません。C文字列の上限は、GDBのset print characters
コマンドで制御できます。
-
svm-print-element-limit <int>
Java配列、ArrayListおよびHashMapをプリティ・プリントするための要素の最大数をカスタマイズします。デフォルト値は10
です。要素を無制限に出力するには、-1
またはunlimited
に設定します。これは、C配列の上限は変更しません。C配列の上限は、GDBのset print elements
コマンドで制御できます。ただし、GDBのパラメータprint elements
がsvm-print-element-limit
の上限です。
-
svm-print-field-limit <int>
Javaオブジェクトのプリティ・プリント・フィールドの最大要素数をカスタマイズします。デフォルト値は50
です。無制限の数のフィールドを出力するには、-1
またはunlimited
に設定します。GDBのパラメータprint elements
が、svm-print-field-limit
の上限です。
-
svm-print-depth-limit <int>
再帰的なプリティ・プリントの最大深度をカスタマイズします。デフォルト値は1
です。直接の子の子が出力されます(ボックス化された値の内容を表示するための正常なデフォルト)。深さを無制限に出力するには、-1
またはunlimited
に設定します。GDBのパラメータprint max-depth
が、svm-print-depth-limit
の上限です。
-
svm-use-hlrep on/off
高レベル表現のプリティ・プリントを有効/無効にします。リストやマップなどの既知の内部構造を持つ一部のJavaデータ構造について、よりデータ指向のビューを提供します。現在、ArrayListおよびHashMapがサポートされています。
-
svm-infer-generics <int>
高レベル表現の汎用型を推測するために考慮される要素の数をカスタマイズします。デフォルト値は10
です。汎用型を推測しない場合は0
、すべての要素の汎用型を推測する場合は-1
またはunlimited
に設定します。
-
svm-print-address absolute/on/off
通常のプリティ・プリントに加えて、アドレスの印刷を有効/無効にします。absolute
モードを使用する場合、圧縮参照も絶対アドレスとして表示されます。アドレスを印刷することは、デフォルトでは無効です。
-
svm-print-static-fields on/off
Javaオブジェクトの静的フィールドの出力を有効または無効にします。静的フィールドの印刷は、デフォルトでは無効になっています。
-
svm-complete-static-variables on/off
拡張されたp
別名の静的フィールド・メンバーの自動補完を有効または無効にします。静的フィールドの自動補完は、デフォルトで有効になっています。
-
svm-selfref-check on/off
データ構造の自己参照チェックを有効または無効にします。プリティ・プリンタは、自己参照型のデータ構造を検出し、無限の再帰を避けるためにさらなる拡張を防ぎます。自己参照チェックはデフォルトで有効になっています。テストでは、この機能は一時的に無効にできます(通常は無効にしません)。