ターゲットとは、 ユーザ・プログラムが持つ実行環境を指します。
多くの場合、
GDBはユーザ・プログラムと同一のホスト環境上で実行されます。
この場合には、
file
コマンドやcore
コマンドを実行すると、
その副作用としてデバッグ・ターゲットが指定されます。
例えば、
物理的に離れた位置にあるホスト・マシン上でGDBを実行したい場合や、
シリアル・ポート経由でスタンドアロン・システムを制御したい場合、
または、
TCP/IP接続を利用してリアルタイム・システムを制御したい場合などのように、
より多くの柔軟性が必要とされる場合、
target
コマンドを使うことによって、
configureによって設定されたGDBのターゲットの種類の中から1つを指定することができます
(ターゲットを管理するコマンド参照)。
ターゲットには3つのクラスがあります。 プロセス、コア・ファイル、 そして、 実行ファイルです。 GDBは同時に、 1クラスにつき1つ、 全体で最高で3つまでアクティブなターゲットを持つことができます。 これにより、 (例えば) コア・ファイルに対して行ったデバッグ作業を破棄することなく、 プロセスを起動してその動作を調べることができます。
例えば、
`gdb a.out'を実行すると、
実行ファイルa.out
が唯一のアクティブなターゲットになります。
コア・ファイル
(おそらくは、
前回実行したときにクラッシュしてコア・ダンプしたもの)
を併せて指定すると、
GDBは2つのターゲットを持ち、
メモリ・アドレスを知る必要がある場合には、
それを知るために2つのターゲットを並行して使用します。
この場合、
まずコア・ファイルを参照し、
次に実行ファイルを参照します。
(典型的には、
これら2つのクラスのターゲットは相互に補完的です。
というのも、
コア・ファイルには、
プログラムが持っている変数などの読み書き可能なメモリ域の内容とマシン・ステータスだけがあり、
実行ファイルには、
プログラムのテキストと初期化されたデータだけがあるからです)。
run
コマンドを実行すると、
ユーザの実行ファイルはアクティブなプロセス・ターゲットにもなります。
プロセス・ターゲットがアクティブな間は、
メモリ・アドレスを要求するすべてのGDBコマンドは、
プロセス・ターゲットを参照します。
アクティブなコア・ファイル・ターゲットや実行ファイル・ターゲットの中のアドレスは、
プロセス・ターゲットがアクティブな間は、
隠された状態になります。
新しいコア・ファイル・ターゲットや実行ファイル・ターゲットを選択するには、
core-file
コマンドやexec-file
コマンドを使用します
(ファイルを指定するコマンド参照)。
既に実行中のプロセスをターゲットとして指定するには、
attach
コマンドを使用します
(既に実行中のプロセスのデバッグ参照)。
target type parameters
target
コマンドを実行した後にRETキーを押しても、
target
コマンドは再実行されません。
help target
info target
コマンドまたはinfo files
コマンドを使用します
(ファイルを指定するコマンド参照)。
help target name
set gnutarget args
set gnutarget
コマンドを使用して、
ファイルのフォーマットを指定することもできます。
ほとんどのtarget
コマンドとは異なり、
gnutarget
におけるtarget
は、
マシンではなくプログラムです。
ファイルを指定するコマンド を参照してください。注意:
set gnutarget
でファイル・フォーマットを指定するには、 実際のBFD名を知っている必要があります。
show gnutarget
gnutarget
がどのようなファイル・フォーマットを読むよう設定されているかを表示させるには、
show gnutarget
コマンドを使用します。
gnutarget
を設定していない場合、
個々のファイルのフォーマットをGDBが自動的に決定します。
この場合、
show gnutarget
を実行すると
`The current BDF target is "auto"'
と表示されます。
以下に、 一般的なターゲットをいくつか示します (GDBの構成によって、 利用可能であったり利用不可であったりします)。
target exec program
target core filename
target remote dev
target remote
は、
load
コマンドをサポートしています。
これは、
スタブをターゲット・システム上に持っていく方法が別にあり、
かつ、
ダウンロードが実行されたときに破壊されないようなメモリ域にそれを置くことができる場合にのみ役に立ちます。
target sim
target sim load runでうまくいきます。 しかし、 シミュレータによっては特定のメモリ・マップ、 デバイス・ドライバ、 基本的なI/Oを提供するものもありますが、 それらが利用可能であることを前提することはできません。 プロセッサ固有のシミュレータの詳細に関しては、 組み込みプロセッサ の該当するセクションを参照してください。
構成によっては、 以下のターゲットも含まれている可能性があります。
target nrom dev
configureによるGDBの構成によって、 利用可能なターゲットも異なるものになります。 configureの構成次第で、 ターゲットの数は多くなったり少なくなったりします。
多くのリモート・ターゲットでは、 接続に成功すると、 実行プログラムのコードをダウンロードすることが必要となります。
load filename
load
コマンドが使用可能になります。
これが利用可能な場合、
実行ファイルfilenameが
(例えば、
ダウンロードやダイナミック・リンクによって)
リモート・システム上でデバッグできるようになることを意味します。
また、
load
コマンドはadd-symbol-file
コマンドと同様、
ファイルfilenameのシンボル・テーブルをGDB内に記録します。
GDBがload
コマンドを提供していない場合、
それを実行しようとすると
「You can't do that when your target is ...
」
というエラー・メッセージが表示されます。
実行ファイルの中で指定されたアドレスに、
ファイルはロードされます。
オブジェクト・ファイルのフォーマットによっては、
プログラムをリンクするときに、
ファイルをロードするアドレスを指定できるものもあります。
これ以外のフォーマット
(例えば、
a.out)
では、
オブジェクト・ファイルのフォーマットによって固定的にアドレスが指定されます。
load
コマンドを実行後にRETキーを押しても、
コマンドは再実行されません。
MIPS、 PowerPC、 Hitachi SHなどのプロセッサは、 ビッグ・エンディアン、 リトル・エンディアンのどちらのバイト・オーダでも実行することができます。 通常は、 実行ファイルまたはシンボルの中に、 エンディアン種別を指定するビットがあるので、 どちらを使用するかを気にする必要はありません。 しかし、 GDBの認識しているプロセッサのエンディアン種別を手作業で調整することができれば、 便利なこともあるでしょう。
set endian big
set endian little
set endian auto
show endian
これらのコマンドは、 ホスト上でのシンボリック・データの解釈を調整するだけであり、 ターゲット・システムに対しては全く何の影響も持たないということに注意してください。
通常の方法でGDBを実行することのできないマシン上で実行されているプログラムをデバッグするには、 リモート・デバッグ機能を使うのが便利です。 例えば、 オペレーティング・システムのカーネルのデバッグや、 フル機能を持つデバッガを実行するのに十分な機能を持つ汎用的なオペレーティング・システムを持たない小規模なシステムでのデバッグでは、 ユーザはリモート・デバッグ機能を使うことになるかもしれません。
GDBは、 その構成によっては、 特別なシリアル・インターフェイスやTCP/IPインターフェイスを持ち、 これを特定のデバッグ・ターゲット用に使用することができます。 さらに、 GDBには汎用的なシリアル・プロトコルが組み込まれており (GDB固有のもので、 特定のターゲット・システムに固有なものではありません)、 リモート・スタブを作成すれば、 これを使用することができます。 リモート・スタブとは、 GDBと通信するためにリモート・システム上で動作するコードです。
GDBの構成によっては、
他のリモート・ターゲットが利用可能な場合もあります。
利用可能なリモート・ターゲットを一覧表示させるには、
help target
コマンドを使用します。
他のマシン上で実行中のプログラムをデバッグするには (ターゲット・マシンをデバッグするには)、 そのプログラムを単独で実行するために通常必要となる事前条件をすべて整える必要があります。 例えば、 Cのプログラムの場合、
次に、 ユーザ・プログラムがシリアル・ポートを使って、 GDBを実行中のマシン (ホスト・マシン) と通信できるように準備します。 一般的には、以下のような形になります。
gdbserver
という補助プログラムを使うこともできます。
詳細については、
gdbserver
プログラムの使用
を参照してください。
デバッグ・スタブはリモート・マシンのアーキテクチャに固有のものです。 例えば、 SPARCボード上のプログラムをデバッグするには`sparc-stub.c'を使います。
以下に実際に使えるスタブを列挙します。 これらは、 GDBとともに配布されています。
i386-stub.c
m68k-stub.c
sh-stub.c
sparc-stub.c
sparcl-stub.c
GDBとともに配布されるREADMEファイルには、 新しく追加された他のスタブのことが記されているかもしれません。
各アーキテクチャ用のデバッグ・スタブは、 3つのサブルーチンを提供します。
set_debug_traps
handle_exception
が実行されるよう設定します。
ユーザ・プログラムは、
その先頭付近でこのサブルーチンを明示的に呼び出さなければなりません。
handle_exception
handle_exception
が実行されるよう設定されます。
ユーザ・プログラムが実行中に
(例えば、ブレイクポイントで)
停止すると、
handle_exception
が制御権を獲得し、
ホスト・マシン上のGDBとの通信を行います。
これが、
通信プロトコルが実装されている部分です。
handle_exception
は、
ターゲット・マシン上でGDBの代理として機能します。
それはまず、
ユーザ・プログラムの状態に関する情報を要約して送ることから始めます。
次に、
GDBが必要とする情報を入手して転送する処理を継続します。
これは、
ユーザ・プログラムの実行を再開させるようなGDBコマンドが実行されるまで続きます。
そのようなコマンドが実行されると、
handle_exception
は、
制御をターゲット・マシン上のユーザ・コードに戻します。
breakpoint
handle_exception
に、
つまり事実上GDBに渡されます。
マシンによっては、
シリアル・ポートから文字を受け取るだけでトラップが発生することもあります。
このような場合には、
ユーザ・プログラム自身からbreakpoint
を呼び出す必要はなく、
ホストのGDBセッションから`target remote'を実行するだけで制御を得ることができます。
これらのどのケースにも該当しない場合、
あるいは、
デバッグ・セッションの開始箇所としてあらかじめ決めてあるところでユーザ・プログラムが停止することを
単に確実にしたいのであれば、
breakpoint
を呼び出してください。
GDBとともに配布されるデバッグ用スタブは、 特定のチップのアーキテクチャ用にセットアップされたものですが、 デバッグのターゲット・マシンに関してそれ以外の情報は持っていません。
まず最初に、 どのようにしてシリアル・ポートと通信するかをスタブに教えてやる必要があります。
int getDebugChar()
getchar
と同一かもしれません。
これら2つを区別したい場合を考慮して、
異なる名前が使われています。
void putDebugChar(int)
putchar
と同一かもしれません。
これら2つを区別したい場合を考慮して、
異なる名前が使われています。
実行中のユーザ・プログラムをGDBが停止できるようにしたいのであれば、
割り込み駆動型のシリアル・ドライバを使用して、
^C
(control-C文字、
すなわち`\003')
を受信したときに停止するよう設定する必要があります。
GDBは^C
を使って、
リモート・システムに対して停止するよう通知します。
デバッグ・ターゲットが適切なステータス情報をGDBに対して返せるようにするためには、
おそらく標準のスタブを変更する必要があるでしょう。
美しい方法ではありませんが、
とりあえず手っ取り早くこれを実現する方法は、
ブレイクポイント命令を実行することです
(この方法が「美しくない」のは、
GDBがSIGINT
ではなくSIGTRAP
を報告してくる点にあります)。
ユーザが提供する必要のあるルーチンには、 ほかに以下のようなものがあります。
void exceptionHandler (int exception_number, void *exception_address)
exceptionHandler
の助けを借りなくても自分で割り込みをマスクすることができます。
void flush_i_cache()
また、次のライブラリ・ルーチンが使用可能であることを確かめなければなりません。
void *memset(void *, int, int)
memset
です。
フリーのlibc.a
を持っていれば、
そこにmemset
があります。
フリーのlibc.a
がなければ、
memset
をハードウェアの供給元から入手するか、
自分で作成する必要があります。
GNU Cコンパイラを使っていないのであれば、
他の標準ライブラリ・サブルーチンも必要になるかもしれません。
これは、
スタブによっても異なりますが、
一般的にスタブは、
gcc
がインライン・コードとして生成する共通ライブラリ・サブルーチンを使用する可能性があります。
要約すると、 ユーザ・プログラムをデバッグする準備が整った後、 以下の手順に従わなければなりません。
getDebugChar
,putDebugChar
,flush_i_cache
,memset
,exceptionHandler
.
set_debug_traps(); breakpoint();
exceptionHook
という変数を提供する必要があります。
通常は、
以下のように使います。
void (*exceptionHook)() = 0;しかし、
set_debug_traps
が呼び出される前に、
ユーザ・プログラム内のある関数を指すようこの変数を設定すると、
トラップ
(例えば、
バス・エラー)
で停止した後にGDBが処理を継続実行するときに、
その関数が呼び出されます。
exceptionHook
によって指される関数は、
1つの引数付きで呼び出されます。
それは、
int
型の例外番号です。
target remote
コマンドを使って通信を確立します。
引数には、
シリアル回線に接続された装置名または
(通常はターゲットと接続されたシリアル回線を持つ端末サーバの)
TCPポートを指定することで、
ターゲット・マシンとの通信方法を指定します。
例えば、
`/dev/ttyb'という名前の装置に接続されているシリアル回線を使うには、
target remote /dev/ttybとします。 TCP接続を使うには、
host:port
という形式の引数を使用します。
例えば、
manyfarms
という名前の端末サーバのポート2828に接続するには、
target remote manyfarms:2828とします。
ここまでくると、 データの値の調査、 変更、 リモート・プログラムのステップ実行、 継続実行に通常使用するすべてのコマンドを使用することができます。
リモート・プログラムの実行を再開し、
デバッグするのをやめるには、
detach
コマンドを使います。
GDBがリモート・プログラムを待っているときにはいつでも、 割り込み文字 (多くの場合 C-C) を入力すると、 GDBはそのプログラムを停止しようとします。 これは成功することも失敗することもありますが、 その成否は、 リモート・システムのハードウェアやシリアル・ドライバにも依存します。 割り込み文字を再度入力すると、 GDBは以下のプロンプトを表示します。
Interrupted while waiting for the program. Give up (and stop debugging it)? (y or n)
ここでyを入力すると、 GDBはリモート・デバッグ・セッションを破棄します (後になって再実行したくなった場合には、 接続するために`target remote'を再度使用します)。 nを入力すると、 GDBは再び待ち状態になります。
GDBとともに提供されるスタブ・ファイルは、 ターゲット側の通信プロトコルを実装します。 そしてGDB側の通信プロトコルは、 GDBのソース・ファイル`remote.c'に実装されています。 通常は、 これらのサブルーチンに通信処理を任せて、 詳細を無視することができます (独自のスタブ・ファイルを作成するときでも、 詳細については無視して、 既存のスタブ・ファイルをもとにして作成を始めることができます。 `sparc-stub.c'が最もよく整理されており、 したがって最も読みやすくなっています)。
しかし、 場合によっては、 プロトコルについて何かを知る必要が出てくることもあるでしょう。 例えば、 ターゲット・マシンにシリアル・ポートが1つしかなく、 GDBに対して送られてきたパケットを検出したときに、 ユーザ・プログラムが何か特別なことをするようにしたい場合です。
以下の例では、 `<-'と`->'が、 それぞれ転送されたデータと受信されたデータを示すために使われています。
(確認メッセージを除く) すべてのGDBコマンドとそれに対する応答は、 packet(パケット)として送信されます。 packetは、 文字`$'で始まり、 その後ろに実際のpacket-data(パケット・データ)が続きます。 さらにその後ろに、 終端文字`#'と2桁のチェックサム値が続きます。
$
packet-data#
checksum
ここで、 2桁の数字から構成されるchecksumは、 先頭の`$'と終端の`#'の間にあるすべての文字の値を合計したものを 256で割った余りとして計算されます (8ビットの無符合チェックサム)。
プロトコル実装者は、 GDB 5.0よりも古いバージョンのプロトコル仕様においては、 必須ではないものの、 2桁の数字のsequence-id(シーケンスID)が含まれていたことに注意する必要があります。
$
sequence-id:
packet-data#
checksum
このsequence-idは確認メッセージの末尾に付加されていました。 GDBがsequence-idを出力するようになっていたことは過去に一度もありません。 GDB 5.0以降に追加されたパケットを処理するスタブは、 sequence-idを受け付けてはなりません。
ホスト・マシンまたはターゲット・マシンがパケットを受信したとき、 最初に期待される応答は確認メッセージです。 これは単一文字で、 (パッケージが正しく受信されたことを示す) `+'または (再送要求を示す) `-'です。
<-$
packet-data#
checksum ->+
ホスト (GDB) がcommand(コマンド)を送信し、 ターゲット (ユーザ・プログラムに組み込まれたデバッグ・スタブ) がresponse(応答)を送信します。 ステップ実行コマンドや継続実行コマンドの場合には、 操作が完了した (ターゲットが再び停止した) ときにのみ応答が送信されます
packet-dataは、 `#'と`$'を除く任意の文字が連続したものです (`X'パケットについてはこれら以外にも除外される文字があります)。
パケット内部のフィールドは、 `,'、 `;'、 `:'のいずれかによって区切られなければなりません。 特にことわりがない限り、 数字はすべて16進数で表現し、 先頭のゼロは記しません。
プロトコル実装者は、 GDB 5.0よりも古いバージョンでは、 (sequence-idと潜在的に矛盾するため) パケット内部の3番目の文字が文字`:'であってはならなかったことに注意するべきです。
領域を節約するために、
ある文字が繰り返し現われる回数を符合化する方式を使って応答データ(data)を符号化することができます。
`*'は、
その次の文字が、
`*'の前にある文字の繰り返し回数をASCII符号化したものであることを意味しています。
繰り返し回数の符号化の結果はn+29
となります。
29
を加算することにより、
(繰り返し回数n
を符号化する方式が有意味である)
n >=3
の場合において、
n
に対応する表示可能文字が生成されます。
表示可能文字
`$'、
`#'、
`+'、
`-'、
および、
126を超える数値は使ってはなりません。
いくつかのリモート・システムでは、 繰り返し回数を符号化する別のメカニズムが使われていました。 これは、 大雑把にシスコ符号化と呼ばれています。 この場合は、 文字`*'の後ろには、 パケットのサイズを示す2桁の数字が続きます。
したがって、
"0*
"
は、 "0000"と同等のことを意味します。
いくつかのパケットに対して返されるエラー応答には2文字のエラー番号が含まれます。 この番号は明確には定義されていません。
スタブがサポートしていないコマンド(command)に対しては、 空の応答(`$#00')が返されるべきです。 こうすれば、 プロトコルの拡張が可能です。 最新のGDBは、 この応答を頼りにして、 あるパケットがサポートされているかどうかを判断することができます。
スタブに対しては、 `g'、 `G'、 `m'、 `M'、 `c'、 `s' の各コマンド(command)をサポートすることが要求されています。 これら以外のコマンドはすべて必須ではありません。
以下に、 現在定義されているすべてのコマンド(command)と対応する応答データ(data)の一覧を示します。
パケット | 要求 | 説明 |
拡張ops | !
| 拡張リモート・プロトコルを使用します。 これは一度だけセットすれば十分であり、 設定は持続します。 拡張リモート・プロトコルは`R'パケットをサポートしています。 |
応答`' | 拡張リモート・プロトコルをサポートしているスタブは`'を返します。 これは残念なことに、 プロトコル拡張をサポートしていないスタブが返す応答と同一です。 | |
最後のシグナル | ?
| ターゲットが停止した理由を示します。 応答は、 ステップ実行や継続実行の場合と同じです。 |
応答 | 後述 | |
予約済 | a
| 将来のために予約されています。 |
プログラム引数のセット(予約済) | A arglen, argnum, arg,...
| |
プログラムに渡された`argv[]'配列を初期化します。 arglenには、 16進で符号化されたバイト・ストリームであるargのバイト数を指定します。 詳細については`gdbserver'を参照してください。 | ||
応答OK
| ||
応答E NN
| ||
ボーレートのセット(非推奨) | b baud
| シリアル回線のスピードをbaudに変更します。 |
ブレイクポイントのセット(非推奨) | B addr,mode
| (modeが`S'の場合は) addrによって指定されるアドレスにブレイクポイントをセットします。 また、 (modeが`C'の場合は) addrによって指定されるアドレスのブレイクポイントを削除します。 これは、 `Z'パケットと`z'パケットによって取って代わられました。 |
継続実行 | c addr
| addrは実行を再開すべきアドレスです。 addrが省略された場合、 現在のアドレスにおいて実行を再開します。 |
応答 | 後述 | |
シグナルによる継続実行 | C sig; addr
|
(16進数)sigによって示されるシグナル通知によって継続実行します。
; addrの部分が省略されると、
現在のアドレスから実行を再開します。
|
応答 | 後述 | |
デバッグのトグル(非推奨) | d
| デバッグ・フラグをトグルします。 |
ディタッチ | D
| リモート・システムからGDBをディタッチします。 GDBが接続を切断する前に、 リモート・ターゲットに送られます。 |
応答なし | このパケットを送った後、 GDBはいかなる応答もチェックしません。 | |
予約済 | e
| 将来のために予約されています。 |
予約済 | E
| 将来のために予約されています。 |
予約済 | f
| 将来のために予約されています。 |
予約済 | F
| 将来のために予約されています。 |
レジスタの読み取り | g
| 汎用レジスタの内容を読み取ります。 |
応答XX... |
レジスタ・データの個々のバイトは2桁の16進数字によって表現されます。
レジスタのバイト情報はターゲットのバイト・オーダで転送されます。
個々のレジスタのサイズと`g' packetの中における位置は、
GDBの内部マクロREGISTER_RAW_SIZEおよびREGISTER_NAMEによって決定されます。
いくつかの標準g パケットの仕様を以下に示します。
| |
E NN
| エラーを示します。 | |
レジスタへの書き込み | G XX...
| XX...データの説明については`g'の項を参照してください。 |
応答OK
| 成功を示します。 | |
応答E NN
| エラーを示します。 | |
予約済 | h
| 将来のために予約されています。 |
スレッドのセット | H ct...
| 後続のオペレーション (`m'、 `M'、 `g'、 `G'、 その他) のためのスレッドをセットします。 |
応答OK
| 成功を示します。 | |
応答E NN
| エラーを示します。 | |
クロック・サイクルによるステップ実行(ドラフト) | i addr, nnn
|
単一クロック・サイクルによってリモート・ターゲットをステップ実行します。
, nnnの部分が指定されていれば、
nnnサイクルだけステップ実行します。
addrが指定されていれば、
そのアドレスからステップ実行を開始します。
|
シグナル通知後、クロック・サイクルによるステップ実行(予約済) | I
| 構文とその意味は、 おそらく`i'や`S'と似たものになると思われます。 これらの項を参照してください。 |
予約済 | j
| 将来のために予約されています。 |
予約済 | J
| 将来のために予約されています。 |
キル(kill)要求 | k
| |
予約済 | l
| 将来のために予約されています。 |
予約済 | L
| 将来のために予約されています。 |
メモリの読み取り | m addr, length
| アドレスaddrから始まるlengthバイトのメモリを読み取ります。 GDBもスタブも、 このメモリ転送がワード境界に境界整列されたアクセスを使うものと前提してはいません。 |
応答XX... | XX...はメモリの内容です。 データの一部しか読むことができない場合は、 要求されたバイト数よりも少ない可能性があります。 GDBもスタブも、 このメモリ転送がワード境界に境界整列されたアクセスを使うものと前提してはいません。 | |
応答E NN
| NNはerrnoです。 | |
メモリへの書き込み | M addr,length: XX...
| アドレスaddrから始まるメモリにlengthバイトのデータを書き込みます。 XX...はデータです。 |
応答OK
| 成功を示します。 | |
応答E NN
| エラーを示します (データの一部しか書き込めなかった場合も含まれます)。 | |
予約済 | n
| 将来のために予約されています。 |
予約済 | N
| 将来のために予約されています。 |
予約済 | o
| 将来のために予約されています。 |
予約済 | O
| 将来のために予約されています。 |
レジスタの読み取り(予約済) | p n...
| 「レジスタへの書き込み」の項を参照してください。 |
応答r.... | レジスタの値をターゲットのバイト・オーダで16進符号化したもの。 | |
レジスタへの書き込み | P n...= r...
| レジスタn...に値r...を書き込みます。 r...には、 レジスタ内の個々のバイトについて2桁の16進数字が含まれます (ターゲットのバイト・オーダによる)。 |
応答OK
| 成功を示します。 | |
応答E NN
| エラーを示します。 | |
一般的なクエリー | q query
| クエリー(問い合わせ)queryに関する情報を要求します。 通常GDBのクエリーは大文字で始まります。 ベンダがカスタマイズしたクエリーには、 例えば`qfsf.var'のように、 その企業を表わす(小文字の)接頭語を使うべきです。 queryの後ろには、 `,'または`;'によって区切られたリストが続くこともあります。 スタブは、 完全なquery名にマッチすることを保証しなければなりません。 |
応答XX...
| クエリーの結果を16進符号化したデータです。 応答は空であってはなりません。 | |
応答E NN
| エラー応答です。 | |
応答`' | queryを理解できなかったことを示します。 | |
一般的なセット | Q var= val
| varの値をvalにセットします。 命名規則に関する議論については`q'の項を参照してください。 |
リセット(非推奨) | r
| システム全体をリセットします。 |
リモート再起動 | R XX
| リモート・サーバを再起動します。 XXの部分は必要ではありますが、 明確には定義されていません。 |
ステップ実行 | s addr
| addrは実行を再開するアドレスです。 addrが省略されると、 現在のアドレスから実行を再開します。 |
応答 | 後述 | |
シグナルによるステップ実行 | S sig; addr
| `C'と似ていますが、 継続実行するのではなくステップ実行します。 |
応答 | 後述 | |
検索 | t addr: PP, MM
| アドレスaddrからはじめて、 パターンPPおよびマスクMMにマッチするものを後方検索します。 PPとMMは4バイトです。 addrは少なくとも3桁の数字でなければなりません。 |
スレッドの状態確認 | T XX
| スレッドXXが存在する(alive)かどうかを調べます。 |
応答OK
| スレッドはまだ存在します(alive)。 | |
応答E NN
| スレッドはもう存在しません(dead)。 | |
予約済 | u
| 将来のために予約されています。 |
予約済 | U
| 将来のために予約されています。 |
予約済 | v
| 将来のために予約されています。 |
予約済 | V
| 将来のために予約されています。 |
予約済 | w
| 将来のために予約されています。 |
予約済 | W
| 将来のために予約されています。 |
予約済 | x
| 将来のために予約されています。 |
メモリへの書き込み(バイナリ) | X addr, length:XX...
|
addrはアドレス、
lengthはバイト数、
XX...はバイナリ・データです。
文字
$ 、
# 、
および0x7d は0x7d を使ってエスケープします。
|
応答OK
| 成功を示します。 | |
応答E NN
| エラーを示します。 | |
予約済 | y
| 将来のために予約されています。 |
予約済 | Y
| 将来のために予約されています。 |
ブレイクポイント、ウォッチポイントの削除(ドラフト) | z t, addr, length
| `Z'の項を参照してください。 |
ブレイクポイント、ウォッチポイントの挿入(ドラフト) | Z t, addr, length
| tは以下の種類を示します。 `0' - ソフトウェア・ブレイクポイント、 `1' - ハードウェア・ブレイクポイント、 `2' - ウォッチポイントへの書き込み、 `3' - ウォッチポイントの読み取り `4' - ウォッチポイントへのアクセス。 addrはアドレスです。 lengthはバイト数による長さです。 ソフトウェア・ブレイクポイントの場合、 lengthはパッチを当てられる命令のサイズを指定します。 ハードウェア・ブレイクポイントおよびハードウェア・ウォッチポイントの場合、 lengthは監視されるメモリ域を指定します。 重複するパケットによる潜在的な問題を回避するために、 オペレーションは副作用のないよう(idempotent)に実装しなければなりません。 |
応答E NN
| エラーを示します | |
応答OK
| 成功を示します。 | |
`' | サポートされていない場合の応答です。 | |
予約済 | <other> | 将来のために予約されています。 |
パケット `C'、 `c'、 `S'、 `s'、 `?'は、 以下のいずれであっても応答として受け取ることができます。 パケット `C'、 `c'、 `S'、 `s'の場合、 この応答はターゲットが停止したときにはじめて返されます。 以下において、 `signal number'(シグナル番号)の正確な意味はきちんと定義されていません。 一般的には、 UNIXにおけるシグナルの番号付けの慣習の1つが使われます。
S AA |
AAはシグナル番号です。 |
T AAn...: r...; n...: r...; n...: r...; |
AAは2桁の数字で表わされたシグナル番号です。
n...は16進数のレジスタ番号です。
r...はレジスタの内容をターゲットのバイト・オーダで表現したもので、
そのサイズはREGISTER_RAW_SIZE によって定義されます。
n...は`thread'です。
r...はそのスレッドのプロセスIDで、
16進整数です。
n...は先頭の文字が正当な16進数字以外である文字列です。
GDBは、
このn...とr...のペアを無視して、
次に進むはずです。
これにより、
プロトコルの拡張が可能になります。
|
W AA |
プロセスが終了し、 その終了ステータスがAAです。 これは、 特定の種類のターゲットにのみ適用可能です。 |
X AA |
プロセスはシグナルAAによって停止しました. |
N AA; t...; d...; b... (旧) |
AAはシグナル番号です。 t...はシンボル"_start"のアドレスです。 d...はdataセクションのベース・アドレスです。 b...はbssセクションのベース・アドレスです。 注:Cisco Systems社のターゲットによってのみ利用されます。 この応答と"qOffsets"クエリーの違いは、 前者においては'N'パケットが自然発生的に来るのに対して、 'qOffsets'はホストのデバッガによって開始されたクエリーであるという点です。 |
O XX... |
XX...は、 ASCIIデータを16進符号化したものです。 これは、 プログラムが動作中で、 デバッガが'W'、 'T'、 等々を待ち続けなければならない状況ではいつでも発生し得ます。 |
以下のセット・パケットおよびクエリー・パケットは定義済みです。
カレント・スレッド | q C
| カレント・スレッドのIDを返します。 |
応答QC pid
| pidは16ビットのプロセスIDを16進符号化したものです。 | |
応答* | その他の応答はいずれも古いPID(プロセスID)を示唆します。 | |
すべてのスレッドID | q fThreadInfo
| |
q sThreadInfo
|
ターゲット(OS)から、
すべてのアクティブなスレッドのIDのリストを取得します。
アクティブなスレッドの数が多すぎて1つの応答パケットに入りきらない可能性があるため、
このクエリーは対話的に行われます。
スレッドの全リストを取得するためには、
複数のクエリー/応答シーケンスが必要になるかもしれません。
シーケンスの最初のクエリーはqf ThreadInfo クエリーです。
また、
シーケンス中の後続のクエリーはqs ThreadInfo クエリーです。
| |
注:qL クエリーを置き換えます(後述)。
| ||
応答m <id>
| 単一のスレッドID | |
応答m <id>,<id>...
| カンマで区切られたスレッドIDのリスト | |
応答l
| (アルファベット小文字の「エル」)リストの終端を示します。 | |
ターゲットは、
個々のクエリーに対して、
ビッグ・エンディアンの16進数であるスレッドID(複数可)をカンマで区切ったリストを返します。
GDBは、
個々の応答に対して、
(qs クエリーを使って)
さらにスレッドIDを求める要求を返します。
これは、
ターゲットがl
(アルファベット小文字の「エル」。'last' を表わす)
を返すまで続きます。
| ||
追加のスレッド情報 | q ThreadExtraInfo , id
| |
<id>はビッグ・エンディアンの16進数であるスレッドIDです。 スレッド属性の表示可能な文字列による説明はターゲットOSから取得されます。 この文字列には、 そのスレッドに関してGDBからユーザに知らせたほうが良いとターゲットOSが考えたことであれば、 何でも含まれている可能性があります。 この文字列は、 GDBの`info threads'の表示結果の中に含まれます。 追加のスレッド情報文字列として考えられる例としては、 "Runnable"や"Blocked on Mutex"が挙げられます。 | ||
応答XX... | XX...はASCIIデータを16進符号化したもので、 スレッドの属性に関する追加情報を含む表示可能な文字列から構成されます。 | |
クエリーLISTまたはクエリーthreadLIST(非推奨) | q L startflagthreadcountnextthread
| |
RTOSからスレッド情報を取得します。 startflag (1桁の16進数字) は、 先頭のクエリーを示すときは1、 後続のクエリーを示すときは0です。 threadcount (2桁の16進数字) は、 応答パケットに含まれるスレッド数の最大値です。 nextthread (8桁の16進数字) は、 後続のクエリー (startflagが0) に対するもので、 応答内においてargthreadとして返されます。 | ||
注:このクエリーはq fThreadInfo クエリーによって置き換えられます
(既述)。
| ||
応答q M countdoneargthreadthread...
| ||
count
(2桁の16進数字)
は返されたスレッドの数です。
done
(1桁の16進数字)
は、
まだスレッドがあることを示す場合は0、
もうスレッドがないことを示す場合は1です。
argthread(6)
(8桁の16進数字)
は、
要求パケットの中のnextthreadです。
thread...は、
ターゲットから送られたスレッドIDのシーケンスです。(7)
remote.c:parse_threadlist_response() を参照してください。
| ||
メモリ・ブロックのCRCの計算 | q CRC: addr, length
| |
応答E NN
| エラー(例えば、メモリ・フォルト) | |
応答C CRC32
| 指定されたメモリ域の32ビット周期的冗長性チェック(cyclic redundancy check) | |
セクション・オフセットのクエリー | q Offsets
|
ダウンロードされたイメージを再配置する際にターゲットが使ったセクション・オフセットを取得します。
注:応答にはBss オフセットが含まれていますが、
GDBはこれを無視し、
代わりにBss セクションに対してData オフセットを適用します。
|
応答Text= xxx;Data= yyy;Bss= zzz
| ||
スレッド情報の要求 | q P modethreadid
| |
threadidに対応する情報を返します。 modeは16進符号化された32ビットのモードです。 threadidは16進符号化された64ビットのスレッドIDです。 | ||
応答* |
remote.c:remote_unpack_thread_info_response() を参照してください。
| |
リモート・コマンド | q Rcmd, COMMAND
| |
(16進符号化された)COMMANDは、
実行するために、
ローカルにあるインタープリタに渡されます。
不正なコマンドは、
出力文字列を通じて報告されるはずです。
最終的な結果パケットの前に、
ターゲットがコンソール出力パケットO OUTPUTをいくつか応答する可能性もあります。
実装者は、
スタブのインタープリタへのアクセスを提供することには、
セキュリティ上の問題がある可能性のあることに注意するべきです。
| ||
応答OK
| 出力を伴わないコマンド応答。 | |
応答OUTPUT | 16進符号化された出力文字列OUTPUTを伴うコマンド応答。 | |
応答E NN
| 要求が不正な形式であったことを示します。 | |
応答`' | `q'`Rcmd'が認識できないときに返されます。 |
次の`g'/`G'パケットは以前は定義されていました。 以下においては、 いくつかの32ビット・レジスタが64ビットとして転送されています。 これらのレジスタは、 割り当てられた領域を埋めるためにゼロ拡張または符号拡張される必要があります。 レジスタのバイトは、 ターゲットのバイト・オーダで転送されます。 レジスタのバイトの中の2つの4ビットは、 most-significant、 least-significant の順に転送されます。
MIPS32 | すべてのレジスタは32ビットのサイズとして転送されます。 転送の順序は、 32個の汎用レジスタ、 sr、 lo、 hi、 bad、 cause、 pc、 32個の浮動小数点レジスタ、 fsr、 fir、 fpです。 |
MIPS64 |
すべてのレジスタは
(sr のような32ビットのレジスタも含めて)
64ビットのサイズとして転送されます。
転送の順序はMIPS32 の場合と同じです。
|
ターゲットが再起動される場合のシーケンス例を以下に示します。 再起動による直接の出力はまったくないことに注目してください。
<-R00
->+
ターゲット再起動 <-?
->+
->T001:1234123412341234
<-+
ターゲットを単一命令ごとにステップ実行する場合のシーケンス例を以下に示します。
<-G1445...
->+
<-s
->+
時間経過 ->T001:1234123412341234
<-+
<-g
->+
->1455...
<-+
gdbserver
プログラムの使用
gdbserver
は、
UNIX系システム用の制御プログラムで、
これにより、
通常のデバッグ用スタブをリンクすることなく、
target remote
コマンドによって、
ユーザ・プログラムをリモートのGDBに接続することができます。
gdbserver
は、
デバッグ用スタブに完全に取って代わるものではありません。
gdbserver
は、
GDBが必要とするのと同様のオペレーティング・システムの機能を基本的には必要とするからです。
実際、
リモートのGDBと接続するためにgdbserver
を実行できるシステムであれば、
GDBをローカルに実行することも可能でしょう。
それでも、
gdbserver
はGDBと比較するとかなりサイズが小さいので、
便利なことがあります。
また、
gdbserver
の移植はGDB全体の移植よりも簡単なので、
gdbserver
を使うことで、
新しいシステムでの作業をより早く開始することができます、
最後に、
リアルタイム・システムをターゲットとする開発をしている場合、
リアルタイムな操作に関わるトレードオフのために、
例えばクロス・コンパイルなどによって、
他のシステム上で可能な限り多くの開発作業を行ったほうが便利であるということがあるでしょう。
デバッグ作業に関しても、
gdbserver
を使うことでこれと同じような選択を行うことができます。
GDBとgdbserver
は、
シリアル回線またはTCP接続を経由して、
標準的なGDBリモート・シリアル・プロトコルによって通信します。
gdbserver
はユーザ・プログラムのシンボル・テーブルを必要とはしませんので、
スペースの節約が必要であれば、
プログラムをストリップすることができます。
ホスト・システム上のGDBが、
シンボルに関するすべての処理を実行します。
gdbserver
を使うには、
GDBとの通信方法、
ユーザ・プログラムの名前、
ユーザ・プログラムへの引数を教えてやる必要があります。
構文は、
以下のとおりです。
target> gdbserver comm program [ args ... ]commは (シリアル回線を使うための) 装置名、 あるいは、 TCPのホスト名とポート番号です。 例えば、 `foo.txt'という引数を指定してEmacsをデバッグし、 シリアル・ポート`/dev/com1'経由でGDBと通信するには、 以下のように実行します。
target> gdbserver /dev/com1 emacs foo.txt
gdbserver
は、
ホスト側のGDBが通信してくるのを受動的に待ちます。
シリアル回線の代わりにTCP接続を使うには、
以下のようにします。
target> gdbserver host:2345 emacs foo.txt前の例との唯一の違いは第1引数です。 これは、 ホストのGDBとTCPによって通信することを指定しています。 `host:2345'は、 マシン`host'からローカルのTCPポート2345へのTCP接続を
gdbserver
が期待していることを意味します
(現在のバージョンでは、
`host'の部分は無視されます)。
ターゲット・システム上で既に使われているTCPポートでなければ、
任意の番号をポート番号として選択できます
(例えば、
23
はtelnet
に予約されています)
(8)。
ここで指定したのと同じポート番号を、
ホスト上のGDBのtarget remote
コマンドで使わなければなりません。
target remote
コマンドによってgdbserver
との通信を確立します。
引数には、
装置名
(通常は`/dev/ttyb'のようなシリアル装置)、
または、
host:PORT
という形式でのTCPポート記述子を指定します。
例えば、
(gdb) target remote /dev/ttybでは、 シリアル回線`/dev/ttyb'を介して
gdbserver
と通信します。
また、
(gdb) target remote the-target:2345では、 ホスト`the-target'上のポート2345に対するTCP接続によって通信します。 TCP接続を使う場合には、
target remote
コマンドを実行する前に、
gdbserver
を起動しておかなければなりません。
そうしないと、エラーになります。
エラー・テキストの内容はホスト・システムによって異なりますが、
通常は`Connection refused'のような内容です。
gdbserve.nlm
プログラムの使用
gdbserve.nlm
はNetWareシステム用の制御プログラムです。
これによって、
target remote
コマンドでユーザ・プログラムをリモートのGDBに接続することができます。
GDBとgdbserve.nlm
は、
標準のGDBリモート・シリアル・プロトコルを使って、
シリアル回線経由で通信します。
gdbserve.nlm
はユーザ・プログラムのシンボル・テーブルを必要とはしませんので、
スペースの節約が必要であれば、
プログラムをストリップすることができます。
ホスト・システム上のGDBが、
シンボルに関わるすべての処理を実行します。
gdbserve.nlm
を使うには、
GDBとの通信方法、
ユーザ・プログラムの名前、
ユーザ・プログラムの引数を教えてやる必要があります。
構文は、
以下のとおりです。
load gdbserve [ BOARD=board ] [ PORT=port ] [ BAUD=baud ] program [ args ... ]boardとportがシリアル回線を指定します。 baudは接続に使われるボーレートを指定します。 portとnodeのデフォルト値は0、 baudのデフォルト値は9600bpsです。 例えば、 `foo.txt'という引数を指定してEmacsをデバッグし、 シリアル・ポート番号2、 ボード1を経由して19200bpsの接続でGDBと通信するには、 以下のように実行します。
load gdbserve BOARD=1 PORT=2 BAUD=19200 emacs foo.txt
target remote
コマンドによって
gdbserve.nlm
との通信を確立します。
引数には、
装置名
(通常は`/dev/ttyb'のようなシリアル装置)
を指定します。
例えば、
(gdb) target remote /dev/ttybは、 シリアル回線`/dev/ttyb'を経由して
gdbserve.nlm
と通信します。
いくつかのターゲットでは、 カーネル・オブジェクトの表示がサポートされています。 GDBは、 この機能を使うことで、 オペレーティング・システムと特別に通信を行い、 mutexやその他の同期オブジェクトのようなオペレーティング・システム階層におけるオブジェクトに関する情報を表示することができます。 表示可能なオブジェクトはOSごとに決まっています。
オペレーティング・システムを指定するにはset os
コマンドを使います。
これによりGDBに対して、
初期化するべきカーネル・オブジェクト表示モジュールが指示されます。
(gdb) set os cisco
set os
が成功すると、
GDBはオペレーティング・システムに関していくつかの情報を表示し、
ターゲットに関するクエリー(問い合わせ)に使うことのできる新しいinfo
コマンドが生成されます。
info
コマンドには、
オペレーティング・システムをもとに名前が付与されます。
(gdb) info cisco List of Cisco Kernel Objects Object Description any Any and all objects
さらにサブコマンドを使うことによって、 カーネルが認識している特定のオブジェクトに関して問い合わせることができます。
現時点では、 あるオペレーティング・システムがサポートされているかどうかを判定するには、 実際に試してみるよりほかに方法がありません。