OpenBoot は、逆アセンブラ、レジスタ表示用コマンド、ブレークポイント関連コマンドなどのデバッグツールを提供します。
組み込み逆アセンブラはメモリーの内容を、対応する SPARC アセンブル言語に翻訳します。
表 6-1 に、メモリーの内容を対応するオペコードに逆アセンブルするコマンドを示します。
表 6-1 逆アセンブラコマンド
コマンド |
スタックダイアグラム |
説明 |
---|---|---|
+dis |
( -- ) |
最後に逆アセンブルを終了したところから逆アセンブルを継続します。 |
dis |
( addr -- ) |
指定されたアドレスから逆アセンブルを開始します。 |
dis は指定する任意のアドレスから、メモリーの内容の逆アセンブルを開始します。システムは次の場合に中断します。
逆アセンブルの進行中に任意のキーを押したとき
逆アセンブラの出力が画面一杯になったとき
call op コードまたは jump op コードが現れたとき
中断したら、逆アセンブルを停止することも、+dis コマンドを使用して最後に停止したところから逆アセンブルを継続することもできます。
メモリーアドレスは通常は 16 進で示されますが、シンボルテーブルがある場合は、メモリーアドレスは可能なかぎりシンボルで表示されます。
プログラムに障害が発生したり、ユーザーが Stop-A で中止したり、あるいはブレークポイントに遭遇した結果、プログラムの実行途中でユーザーインタフェースに入ってしまうことがあります。(ブレークポイントについては、「ブレークポイント」で説明します。) 上記の場合には、ユーザーインタフェースは自動的にすべての CPU データレジスタの値をバッファー領域に保存します。デバッグの目的のためにそれらの値を調べたり、変更することができます。
表 6-2 に SPARC のレジスタ操作コマンドを示します。
表 6-2 SPARC レジスタコマンド
コマンド |
スタックダイアグラム |
説明 |
---|---|---|
%f0 〜 %f31 |
( -- value ) |
指定された浮動小数点レジスタの値を返します。 |
%fsr |
( -- value ) |
浮動小数点ステータスレジスタの値を返します。 |
%g0 〜 %g7 |
( -- value ) |
指定されたグローバルレジスタの値を返します。 |
%i0 〜 %i7 |
( -- value ) |
指定された入力レジスタの値を返します。 |
%l0 〜 %l7 |
( -- value ) |
指定されたローカルレジスタの値を返します。 |
%o0 〜 %o7 |
( -- value ) |
指定された出力レジスタの値を返します。 |
%pc %npc %psr %y %wim %tbr |
( -- value ) |
指定されたレジスタの値を返します。 |
.fregisters |
( -- ) |
%f0 から %f31 までの値を表示します。 |
.locals |
( -- ) |
i、l、o レジスタの値を表示します。 |
.psr |
( -- ) |
プログラムステータスレジスタの書式付きで表示します。 |
.registers |
( -- ) |
%g0 から %g7 までのほかに、%pc、%npc、 %psr、%y、%wim、%tbr の値を表示します。 |
.window |
( window# -- ) |
w .locals と同じ。指定されたウィンドウを表示します。 |
ctrace |
( -- ) |
C サブルーチンを示す復帰スタックを表示します。 |
set-pc |
( new-value -- ) |
%pc に new-value を、%npc に (new-value+4) をそれぞれ設定します。 |
to regname |
( new-value -- ) |
上記のうちの任意のレジスタの格納値を変更します。 new-value to regname の形式で使用してください。 |
w |
( window# -- ) |
現在のウィンドウを、%ix、%Lx、または %ox を表示するために設定します。 |
値の確認や変更が終わったら、go コマンドを使用してプログラムの実行を継続できます。保存したレジスタの値 (変更したものを含めて) は、(コピーして) CPU に戻され、保存されたプログラムカウンタによって指定された位置から実行が再開されます。
to を使用して %pc を変更する場合は、%npc も同時に変更する必要があります。(set-pc の方が両レジスタを自動的に変更するので簡単です。)
w および .window コマンドについては、ウィンドウ値 0 は通常、現在のウィンドウを指定します。つまり、プログラムが中断されたときのサブルーチンのアクティブウィンドウです。ウィンドウ値が 1 の場合は、そのサブルーチンの呼び出し元のウィンドウであり、2 の場合はその呼び出し元の呼び出し元を指定します。以下同様に、有効なスタックフレーム数までこの関係が繰り返されます。デフォルトの開始値は 0 です。
ユーザーインタフェースは、スタンドアロンプログラムの開発とデバッグの支援用として、ブレークポイント機能を備えています。(オペレーティングシステムのもとで実行されるプログラムは、一般的にこの機能は使用しないで、オペレーティングシステムのもとで動作するほかのデバッガを使用します。) ブレークポイント機能では、テストプログラムを停止させたい場所で停止することができます。プログラムの実行が停止した後は、レジスタまたはメモリーを調べたり、変更できるほか、ブレークポイントを新たに設定またはクリアすることができます。プログラムの実行は go コマンドで再開できます。
表 6-3 に、プログラム実行の制御、監視用のブレークポイントコマンドを示します。
表 6-3 ブレークポイントコマンド
コマンド |
スタックダイアグラム |
説明 |
---|---|---|
+bp |
( addr -- ) |
指定されたアドレスにブレークポイントを追加します。 |
-bp |
( addr -- ) |
指定されたアドレスからブレークポイントを削除します。 |
--bp |
( -- ) |
最後に設定されたブレークポイントを削除します。 |
.bp |
( -- ) |
現在設定されているすべてのブレークポイントを表示します。 |
.breakpoint |
( -- ) |
ブレークポイントが発生したときに、指定された処理を実行します。このワードは、実行させたい任意の処理を実行するように変更できます。たとえば、ブレークポイントごとにレジスタを表示するには、['] .registers is .breakpoint と入力します。デフォルト処理は .instruction です。複数の処理を実行させるには、実行させたいすべての処理を呼び出す 1 つの定義を作成し、次にそのワードを .breakpoint に読み込みます。 |
.instruction |
( -- ) |
最後に現れたブレークポイントのアドレスとオペコードを表示します。 |
.step |
( -- ) |
シングルステップで実行になったときに指定された処理を実行します (.breakpoint を参照)。 |
bpoff |
( -- ) |
すべてのブレークポイントを削除します。 |
finish-loop |
( -- ) |
このループの終わりまで実行します。 |
go |
( -- ) |
ブレークポイントから処理を継続します。これを利用して、go を発行する前にプロセッサのプログラムカウンタをセットアップすることにより、任意のアドレスに移ることができます。 |
gos |
( n -- ) |
go を n 回実行します。 |
hop |
( -- ) |
(step コマンドに似ています。) サブルーチン呼び出しを 1 つの命令として取り扱います。 |
hops |
( n -- ) |
hop を n 回実行します |
return |
( -- ) |
このサブルーチンの終わりまで実行します。 |
returnL |
( -- ) |
このリーフサブルーチンの終わりまで実行します。 |
skip |
( -- ) |
現在の命令をスキップします (実行しません)。 |
step |
( -- ) |
1 命令を 1 つずつ実行します。 |
steps |
( n -- ) |
step を n 回実行します。 |
till |
( addr -- ) |
指定されたアドレスが現れるまで実行します。 +bp go と等価です。 |
ブレークポイントを使用してプログラムをデバッグするには、次の手順に従います。
テストプログラムをメモリーアドレス 4000 (16 進) へ読み込みます。
詳細は、第 5 章「プログラムの読み込みと実行」を参照してください。一般的に dload を使用するのが最善の方法です。理由は、プログラムのシンボルテーブルが保存されるためです。Ethernet を介してプログラムを読み込めない場合は、boot -h も同じ機能を果たします。
%pc およびそのほかのすべてのレジスタの値が自動的に初期設定されます。
(省略可能) ダウンロードされたプログラムを逆アセンブルして、ファイルが正しく読み込まれているかどうかを確認します。
step コマンドを使用してテストプログラムを 1 命令ずつ実行します。
さらに、ブレークポイントを設定し、実行したり (たとえば、4020 +bp および go コマンドを実行します)、ほかの方法で実行することもできます。
Forth ソースレベルデバッガでは、Forth プログラムのステップ実行およびトレースが可能です。各実行ステップが 1 つの Forth ワードに対応します。
表 6-4 にこのデバッガのコマンドを示します。
表 6-4 Forth ソースレベルデバッガコマンド
コマンド |
説明 |
---|---|
c |
"Continue (継続)"。シングルステップ実行からトレースに切り替え、デバッグ中のワードの実行の残り部分をトレースします。 |
d |
"Down a level (1 レベルダウン)"。今表示された名前のワードをデバッグ対象としてマークし、次にそのワードを実行します。 |
f |
下位の Forth インタプリタを起動します。そのインタプリタを (resume で) 終了させると、F コマンドが実行されたところで制御がデバッガに戻ります。 |
q |
"Quit (終了)"。デバッグ中のワードとそのすべての呼び出し元の実行を強制終了させ、制御をコマンドインタプリタに戻します。 |
u |
"Up a level (1 レベルアップ)"。デバッグ中のワードからデバッグ対象のマークを取り消します。その呼び出し元をデバッグ対象としてマークし、それまでデバッグされていたワードの実行を終了します。 |
debug name |
指定された Forth ワードをデバッグ対象としてマークします。以降は、 name を実行しようとするたびに、必ず Forth ソースレベルデバッガを起動します。debug の実行後は、debug-off でデバッグがオフされるまではシステムの実行速度が落ちることがあります。("." などの基本 Forth ワードはデバッグしないでください。) |
debug-off |
Forth ソースレベルデバッガをオフにします。以降、ワードのデバッグは行われません。 |
resume |
下位インタプリタを終了し、制御をデバッガのシングルステップ実行に戻します (この表の F コマンドを参照)。 |
stepping |
"シングルステップ (実行) モード" に設定し、デバッグ中のワードを 1 ステップずつ対話的に実行できるようにします。シングルステップモードはデフォルトです。 |
tracing |
Forth ソースレベルデバッガを "トレースモード" に設定します。このモードは、デバッグ中のワードの実行をトレースし、その間そのワードが呼び出す各ワードの名前とスタックの内容を表示します。 |
<space-bar> |
今表示されたワードを実行し、次のワードのデバッグに移ります。 |
すべての Forth ワードはそれぞれに、「コンポーネント」ワードと呼べる 1 つまたは複数の一連のワードとして定義されています。指定されたワードをデバッグしている間に、デバッガは、そのワードの各「コンポーネント」ワードを実行中にスタックの内容に関する情報を表示します。各コンポーネントワードを実行する直前に、デバッガはスタックの内容と、実行されようとしているコンポーネントワードの名前を表示します。
トレースモードでは、そのコンポーネントワードがそこで実行され、プロセスは次のコンポーネントワードに引き継がれます。
ステップモード (デフォルト) では、ユーザーがデバッガの実行動作を制御します。各コンポーネントワードの実行前に、ユーザーはプロンプトで表 6-4 にある 1 つのキー操作のどれかを求められます。
ftrace コマンドは、最後の例外割り込み時に実行されていた Forth ワード処理を表示します。次に ftrace の例を示します。
ok : test1 1 ! ; ok : test2 1 test1 ; ok test2 Memory address not aligned ok ftrace ! Called from test1 at ffeacc5c test1 Called from test2 at ffeacc6a (ffe8b574) Called from (interpret at ffe8b6f8 execute Called from catch at ffe8a8ba ffefeff0 0 ffefebdc catch Called from (fload) at ffe8ced8 0 (fload) Called from interact at ffe8cf74 execute Called from catch at ffe8a8ba ffefefd4 0 ffefebdc catch Called from (quit at ffe8cf98 |
上記の例では、test2 が test1 を呼び出し、test1 は境界に合わないアドレスに値を格納しようとします。その結果、Memory address not aligned という例外が発生します。
ftrace の出力の 1 行目は、例外を発生させた最後のコマンドを示しています。2 行目以降は、その後のコマンドが呼び出されようとしていたメモリーアドレスを示しています。
最後の 13 行は、通常どの ftrace の出力とも同じですが、これは、それが Forth インタプリタが入力ストリームからワードを解釈するときに有効な呼び出し処理であるからです。