print exp
データを評価する更に低レベルの方法は `x' コマンドを用いることです。 このコマンドは、指定されたアドレス上のデータを調査し、指定された フォーマットで表示します。
#define
コマンドで定義されたシンボルは含まれ
ません。
キャストは、C言語だけでなく、全ての言語においてサポートしています。 というのも、ポインタが指す数をキャストすることは、メモリ内のその アドレス上の構造を調査するのに便利だからです。
GDB は、プログラミング言語が許可している式に加えて、次の3種類の オペレータをサポートしています:
@
::
式内の変数は、選択されたフレーム上で解釈されます(“6.3 フレームの選択”をご覧下さい); これらは、そのフレームにおいて処理が実行されている時、プログラミング 言語のスコープのルールに従って可視のものか、又はグローバル (もしくは static) のどちらかでなければなりません。このことは、次のような関数の 場合、
foo (a) int a; { bar (a); { int b = test (); bar (b); } }
a
はプログラムが関数 foo
を実行している時は
いつでも利用可能ですが、変数 b
は b
が宣言されている
ブロックの中をプログラムが実行している時にしか見えません。
特例として、スコープが単一ファイルに限定されていて、カレントな実行 ポイントがそのファイルにない場合でさえ、変数や関数を参照することが できるようにすることが可能です。しかし、このことは、同一名称の変数や 関数を (もし、それらが異なったソースファイル上に存在するとして) 一つ 以上参照できてしまうことになります。このようなケースでは、どちらが 参照されるのかは定義されていません。もし、あなたが望むなら、これらの うちのどれか一つを、コロン-コロンという構造を用いて指定することが できます。
block::variable
これは、バイナリ・オペレータ `@' による仮想配列という構造に よって可能になります。`@' の左側のオペランドは配列にしたい最初の 要素で、単一のオブジェクトです。右側のオペランドは配列の長さです。 結果は、全ての要素が左側の引数の型になるような配列値です。最初の要素は、 正に左側の引数であり; 2番目の要素は最初の要素と同様の型がメモリのバイト列として続いて接して いるとみなし、残りも同様です。例を示しましょう。もし、プログラムに
int *array = (int *) malloc (len * sizeof (int));
array
の内容を次のようにして表示する
ことができます。
p *array@len
$1 = { next = 0x0, flags = { sweet = 1, sour = 1 }, meat = 0x54 "Pork" }
$1 = {next = 0x0, flags = {sweet = 1, sour = 1}, meat = 0x54 "Pork"}
例えば、次のような宣言が与えられていた場合、
typedef enum {Tree, Bug} Species; typedef enum {Big_tree, Acorn, Seedling} Tree_forms; typedef enum {Caterpiller, Cocoon, Butterfly} Bug_forms; struct thing { Species it; union { Tree_forms tree; Bug_forms bug; } form; }; struct thing foo = {Tree, {Acorn}};
$1 = {it = Tree, form = {tree = Acorn, bug = Cocoon}}
$1 = {it = Tree, form = {...}}
出力フォーマットの簡単な使い方は、既に計算済みの値をどのように 表示するかを指示するというものです。これは、`print' コマンドの 最初の引数を、スラッシュで始まってフォーマット文字で終わらせることに よって実現できます。フォーマット文字には、次のようなものがサポート されています:
p/x $pc
変数値の履歴にある最後に表示した値を異なったフォーマットで再表示したい 場合は、式なしの `print' コマンドにフォーマットを指定して下さい。 例えば、`p/x' は最後に表示した値を16進数で再表示します。
`x' はスラッシュの後にフォーマットに関する記述、そしてその後に アドレスに関する記述を受け付けます。式には (もし通したとしても) ポインタ 値が使えないので; そこにはメモリのバイト列の整数値やアドレスが使われます。 式の詳細は、“8.1 式”を参照して下さい。 例えば、`x/4xw $sp' はスタックポインタ上のメモリを4ワードの 16進数で表示します。
このケースにおける出力フォーマットでは、調査するメモリの大きさと、 そのユニットの内容をどのように表示するのかということを記述します。 これには、この後に説明する1つか2つの文字で指定します:
次に示す文字は、まさに調査対象のユニットのサイズを記述します:
多くのアセンブラとCPU設計者は、祖先となる1970年代のマシンが実際に 2バイトのワードを利用していたという名残により、`ワード'をいまだ 16ビットのサイズとして定義しています。しかし、一般的に言うと、 `ワード'は、マシンが通常レジスタで操作したり記憶したりするサイズだと いうのが、語源です。GDB が動作する全てのマシンにおいて、このサイズは 32ビットです。
あなたは、また、調査対象アドレスも省略可能です。この場合、ユニットが 最後に調査されたアドレスが使用されます。これは、データをベースとして ユニットサイズが計算されるような、文字列とインストラクション・ フォーマットのためのものです: というのも、次の文字列やインストラクションは正しい位置から調査を 開始しなければならないからです。`print' コマンドは、時折 `x' コマンドのためのデフォルトアドレスを設定します; メモリ上に位置する値が表示された時、デフォルトで同一の 位置が設定されています。`info line' はまた `x' と同様に 指定された行のマシンコードの開始アドレスにデフォルトを設定し、 `info breakpoints' は、最後に表示されたブレークポイントの アドレスにデフォルトを設定します。
RET により `x' コマンドがリピートされた時は全く同様の内容を リピートしません: 指定されたアドレスは (もしあれば) 無視され、リピートされたコマンドは 同一の場所のかわりに連続したメモリ位置を調査します。
あなたは、更に、コマンドに対してスラッシュの後に (また、もしあれば フォーマット文字の前に) 繰り返し回数を書くことで、いくつかの連続的な メモリユニットを調査することができます。繰り返し回数は10進数の整数で なければなりません。これは、`x' コマンドがリピートされた時と 同様な効果を持ち、出力は行ごとのいくつかのユニットに対して、より コンパクトになります。例えば、
x/10i $pc
x/10
`x' コマンドによって表示されるアドレスとその内容は、
あまりにも多すぎ、それらを記録するのが邪魔なので、変数履歴に代入
されません。そのかわりに、GDB は、簡易変数 $_
と $__
の
値を式で使うという別な手段を提供しています。
`x' コマンドの後、最後に調査されたアドレスは、
式内の簡易変数 $_
によって参照可能となります。そのアドレスの
内容は、調査されたならば、簡易変数 $__
においても有効です。
もし、`x' コマンドが繰り返されたならば、アドレスと内容は最後に 表示されたメモリユニットの形態として保存されます; これは、最後の行の出力においていくつかのユニットが表示された時の 最後のアドレス表示の内容とは異なります。
`disassemble' という特別なコマンドは、与えられたメモリレンジを マシン・インストラクションとしてダンプします。デフォルトのメモリ レンジは、選択されているフレーム上のプログラムカウンタを取り囲む 関数の範囲です。このコマンドへ一つの引数を渡した場合、これは、 プログラムカウンタ値となります; この値を取り囲む関数がダンプされます。2つの引数を渡した場合は、 ダンプするアドレスの範囲を示します。(最初が包括的、2つ目が排他的。)
2: foo = 38 3: bar[5] = (struct hack *) 0x3804
もし、式がローカル変数を参照している場合、それが設定された語意上の
文脈の範囲外では意味を成しません。このような式は、実行処理が語意上の
文脈の中にある時にのみ、表示されます。例えば、あなたが関数内で、
引数 name
を表示する `display name' というコマンドを与えた
場合、この引数はプログラムがその関数内部で停止する時に表示されますが、
それ以外の場所に停止した時は (この引数がどこにも存在しないので) 表示
されません。
表示された値は、あなたがそれによって参照できるようにするために、 履歴番号が付与されます。 これらは、1ではじまる連続する整数値です。`print' は、指定 された値を表示する前に `$num = ' という形式で履歴番号を 表示します; この num が履歴番号です。
以前の任意の値を参照する場合、その値の履歴番号を後に持つ `$' を
使います。`print' によって表示される出力は、あなたにこのことを
気付かせるようにデザインされています。単なる $
は履歴上の最も
最近の値を参照し、$$
は、その直前の値を参照します。
例えば、ポインタの構造を表示した後で、その内容を再び見たくなったと仮定 しましょう。これは、次のように入力するだけで十分です。
p *$
p *$.next
履歴は値を記録しており、式を記録しているわけではないことに注意して
下さい。x
の値が4であるとして、あなたが次のコマンドを入力したら:
print x set x=5
x
の内容が変更されたと
しても、`print' コマンドが表示した4のままです。
簡易変数は、`$' ではじまる名称を持ちます。`$' ではじまる 任意の名称は、既に定義済みのレジスタ名 (“8.9 レジスタ”をご覧下さい) を除けば、 簡易変数として扱われます。
あなたは、プログラムで変数値を設定する時のように、式による代入を 使うことで簡易変数に値を保存することができます。例えば:
set $foo = *object_ptr
object_ptr
でポイントされるオブジェクトの
内容値を $foo
に保存することができます。
簡易変数を最初に使った場合、まずそれは生成されます;
しかしその値は、あなたが新しい値を設定するまでは void
値です。
あなたは、いつでも、他の代入を行い、値を変更することができます。
簡易変数には、決まった型がありません。あなたは、簡易変数に対して、 既に設定されている値とは異なった型であったとしても、任意の型の値を 設定することができます。簡易変数は、たとえカレント値がどんな型で あっても式になりえます。
set $i = 0 print bar[$i++]->contents ...RET を入力することで、このコマンドを繰り返す。
$_
という変数は `x' コマンドによって最後に調査した
アドレスが自動的に設定されます(“8.5.1 メモリの調査”をご覧下さい)。
`x' で調査するためのデフォルトアドレスを供給する他のコマンドも
また、$_
にそのアドレスを設定します;
これらのコマンドには、`info line' と `info breakpoint' も
含みます。
$__
という変数は、`x' コマンドが最後に調査したアドレスで
見つかった値が自動的に設定されます。
$pc
と $sp
という名称は、
全てのマシンにおいてプログラムカウンタ及びスタックポインタとして使われ
ます。また、$fp
がカレントのスタックフレームの内容を持つ
レジスタとして用いられ、$ps
はプロセッサステータスの内容を保持
しているレジスタとして使われています。これらの標準レジスタ名は、あなた
のマシンにおいて info registers
コマンドを使ってみると、
異なった名称で表示されるかもしれません。例えば、SPARC では、
info registers
はプロセッサステータス・レジスタとして
$psr
を表示しますが、これを $ps
で参照することもできます。
GDB は、レジスタ値がこの方法で調査された場合、普通のレジスタが持つ内容を 整数値とみなします。あるマシンはレジスタ値が浮動小数点値とみなされる ような; 浮動小数点値を記憶できる特別なレジスタを持っています。 しかし、(たとえ、あなたが print コマンドを使って、 `print/f $regname' のように浮動小数点値として表示しようと したとしても) 普通のレジスタの内容を浮動小数点値とみなす方法は ありません。
あるレジスタは“raw”や“virtual”という独特のデータフォーマットを 持っています。これは、オペレーティング・システムによって保存された レジスタの内容が、あなたのプログラムから通常見える内容と同じでない データフォーマットのことです。例えば、68881浮動小数点演算コ・プロセッサの レジスタは、“拡張された”フォーマットで保存されますが、全ての C言語プログラムは、結果を“double”フォーマットで要求します。 このようなケースの場合、GDB は、通常、仮想 (virtual) フォーマット (あなたのプログラムが理解できるフォーマット) のみで動作しますが、 `info registers' コマンドは、両方のフォーマットのデータを表示します。
レジスタ値は選択されているスタックフレームに対して相対的 です(“6.3 フレームの選択”をご覧下さい)。あなたが値を得る時、もし離れたところにある 全てのスタックフレームが破棄され、それらに保存されていたレジスタが 復活されたならば、レジスタは内容を持っています。全てのレジスタの 実際の内容を見る手段としては (`frame 0' などのように) 最深部の フレームを選択しなければなりません。
あるレジスタは、関数値を返すことに使われるという理由のために、 決して保存されることはありません(それらの代表的な値はゼロか1です); これらのレジスタにとって、相対関係は無意味です。
p/x $pc
x/i $pc
set $sp += 4
$sp
への値設定は
許可されません。