Solaris モジューラデバッガ

第 7 章 モジュールプログラミング API

この章では、MDB デバッガモジュール API に含まれている構造体と関数について説明します。ヘッダーファイル <sys/mdb_modapi.h> にこれらの関数のプロトタイプが含まれているほか、SUNWmdbdm パッケージには、ディレクトリ /usr/demo/mdb にあるサンプルモジュールのソースコードが入っています。

デバッガモジュールのリンケージ

_mdb_init()

const mdb_modinfo_t *_mdb_init(void);

リンケージと識別を可能にするために、各デバッガモジュールには _mdb_init() という関数を提供する必要があります。この関数は、自動変数として宣言されない固定の mdb_modinfo_t 構造体を指すポインタを返します。これについては、<sys/mdb_modapi.h> に次のように定義されています。

typedef struct mdb_modinfo {
			ushort_t mi_dvers;              /* デバッガの API のバージョン番号 */
			const mdb_dcmd_t *mi_dcmds;     /* NULL で終了する dcmd のリスト */
			const mdb_walker_t *mi_walkers; /* NULL で終了する walk のリスト */
} mdb_modinfo_t;

mi_dvers メンバーは API のバージョン番号を識別するためのもので、常に MDB_API_VERSION に設定されます。このようにして現在のバージョン番号が各デバッガモジュールの中にコンパイルされているので、デバッガは、モジュールが使用するアプリケーションのバイナリインタフェースを識別し、検証できます。デバッガは、自らのバージョンより新しいバージョンの API に対してコンパイルされているモジュールは読み込みません。

mi_dcmdsmi_walkers というメンバーは、NULL でない場合はそれぞれ dcmd と walker の定義構造体の配列を指しています。どちらの配列も NULL 要素で終了していなければなりません。これらの dcmd と walker は、モジュールを読み込むプロセスの一部としてデバッガによってインストールされ、登録されます。dcmd または walker が正しく定義されていなかったり、名前が重複していたり無効であったりした場合、デバッガはそのモジュールの読み込みを拒否します。dcmd と walker の名前には、引用符や括弧など、デバッガにとって特別な意味を持つ文字を入れることはできません。

モジュールでは、モジュール API を使用して _mdb_init() のコードを実行し、読み込むべきかどうかを判定することもできます。たとえば、特定のシンボルが存在する場合だけ、特定のターゲットに対して該当するモジュールは存在します。これらのシンボルが見つからない場合、このモジュールは _mdb_init() 関数から NULL を返します。この場合、デバッガによってこのモジュールの読み込みは拒否され、該当するエラーメッセージが出力されます。

_mdb_fini()

void _mdb_fini(void);

mdb_alloc() によって以前に割り当てられた固定メモリーの解放など、読み込み解除に先立って一定のタスクを実行するモジュールの場合は、_mdb_fini() という関数を宣言してこれを行うことができます。この関数はデバッガでは必要とされません。この関数を宣言すると、モジュールの解除の前に一度呼び出されます。ユーザーがデバッガの終了を要求したとき、またはユーザーが ::unload 組み込み dcmd を使用して明示的にモジュールを解除したときに、モジュールは解除されます。

dcmd の定義

int dcmd(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv);

dcmd は dcmd() の宣言に似た関数によって実装されます。この関数は次の 4 つの引数を受け取り、整数のステータスを返します。

addr

現在のアドレス。ドットともいう。dcmd の開始時点では、このアドレスはデバッガのドット " . " 変数の値に対応しています。

flags

次のフラグの 1 つ以上の論理和を含む整数

DCMD_ADDRSPEC

明示的なアドレスが ::dcmd の左に指定された

DCMD_LOOP

dcmd が ,count 構文を使ってループの中で呼び出されたか、またはパイプラインによってループの中で呼び出された

DCMD_LOOPFIRST

この dcmd 関数の呼び出しは、最初のループまたはパイプラインの呼び出しに対応している

DCMD_PIPE

dcmd がパイプラインからの入力に伴って呼び出された

DCMD_PIPE_OUT

dcmd がパイプラインに対して設定された出力に伴って呼び出された

便利な DCMD_HDRSPEC() マクロが用意されており、dcmd はフラグをテストしてヘッダーラインを出力するかどうかを決定できます。ヘッダーラインを出力するのは、ループの一部として呼び出されていない、あるいはループまたはパイプラインの繰り返しの最初の場合です。

argc

argv 配列内の引数の数

argv

コマンド行の ::dcmd の右側に指定された引数の配列。この引数は文字列の場合と整数値の場合があります。

dcmd 関数は、<sys/mdb_modapi.h> に定義されている、次の整数値のいずれかを返します。

DCMD_OK

dcmd は正常に完了した

DCMD_ERR

何らかの理由により dcmd は失敗した

DCMD_USAGE

無効な引数が指定されたため、dcmd は失敗した。この値が返される場合は、以降に述べるように dcmd の使用に関するメッセージが自動的に出力される

DCMD_NEXT

次の dcmd 定義がある場合は、同じ引数で自動的に呼び出される

DCMD_ABORT

dcmd が失敗したため、現在のループまたはパイプラインは強制終了される。この戻り値は DCMD_ERR に似ているが、現在のループまたはパイプラインを続行できないことを示す

各 dcmd は <sys/mdb_modapi.h> に定義されているように、サンプルの dcmd() プロトタイプにしたがって定義された関数と、それに対応する mdb_dcmd_t 構造体から構成されています。この構造体は、次のフィールドから構成されています。

const char *dc_name

dcmd の文字列名。先頭に "::" が付かない。この名前には、$ または ` などの MDB メタキャラクタを含めることはできない

const char *dc_usage

dcmd に対するオプションの用法文字列。dcmd が DCMD_USAGE を返すとこの文字列が出力される。たとえば、dcmd がオプション -a-b を受け付ける場合、dc_usage は "[-ab]" と設定される。dcmd が引数を受け付けない場合、dc_usage は NULL に設定される。用法文字列が ":" で始まっている場合、dcmd でアドレスを明示的に指定する必要があり、フラグパラメタに DCMD_ADDRSPEC を設定する必要があることを示す。用法文字列が "?" で始まっている場合、dcmd はオプションでアドレスを受け付けることを示す。これらのヒントに従って、用法メッセージも変更される

const char *dc_descr

dcmd の目的を簡単に説明する、必須の記述文字列。この文字列は単一行のテキストで構成される

mdb_dcmd_f *dc_funcp

dcmd を実行するために呼び出される関数を指すポインタ

void (*dc_help)(void)

dcmd のヘルプ関数を指すオプションの関数ポインタ。このポインタが NULL 以外の値の場合、ユーザーが ::help dcmd を実行すると、この関数が呼び出される。この関数では mdb_printf() を使用して詳細情報や例を表示できる

walker の定義

int walk_init(mdb_walk_state_t *wsp);
int walk_step(mdb_walk_state_t *wsp);
void walk_fini(mdb_walk_state_t *wsp);

walker は initstep、および fini の 3 つの関数で構成されており、これらの関数は上記のプロトタイプの例に従って定義されています。walker は、mdb_walk() などのいずれかの walk 関数が呼び出されたとき、またはユーザーが ::walk 組み込み dcmd を実行したときに、デバッガによって起動されます。<sys/mdb_modapi.h> に定義されているように、walk が開始されると、MDB は walker の init 関数を呼び出し、新規 mdb_walk_state_t 構造体のアドレスをこの関数に渡します。

typedef struct mdb_walk_state {
			mdb_walk_cb_t walk_callback;    /* 実行のためのコールバック */
			void *walk_cbdata;              /* 専用データのコールバック */
			uintptr_t walk_addr;            /* 現在のアドレス */
			void *walk_data;                /* walk 専用データ */
			void *walk_arg;                 /* walk 専用引数 */
			void *walk_layer;               /* 配下の層からのデータ */
} mdb_walk_state_t;

walk ごとに個別に mdb_walk_state_t が作成されるため、同じ walker の複数のインスタンスを同時にアクティブにすることができます。たとえば mdb_walk() に指定されているように、state 構造体には、各ステップにおいて walker が呼び出すコールバック (walk_callback)、およびそのコールバックに対する専用データ (walk_cbdata) が含まれています。walk_cbdata ポインタは walker からは隠されているため、この値を変更したり、参照を解除したりすることはもちろん、有効なメモリーを指すポインタとみなすこともできません。

walk の開始アドレスは walk_addr に格納されています。このアドレスは mdb_walk() が呼び出された場合の NULL か、または mdb_pwalk() に指定されているアドレスパラメタのどちらかの値となります。::walk 組み込みコマンドが使用された場合、明示的なアドレスが ::walk の左側に指定されているときは、walk_addr は NULL 以外の値となります。開始アドレスが NULL の walk のことをグローバル walk といいます。NULL 以外の明示的な開始アドレスを持つ walk のことをローカル walk といいます。

walker 専用の記憶領域として walk_data および walk_arg フィールドが用意されています。複雑な walker の場合、補助的な state 構造体を割り当てて、この構造体を指すように walk_data を設定する必要があります。walk が開始されるたびに、walk_arg は、対応する walker の mdb_walker_t 構造体の walk_init_arg メンバーが持つ値に初期設定されます。

場合によっては、複数の walker に同じ init、step、および fini ルーチンを共有させると便利な場合があります。たとえば、MDB genunix モジュールは、各カーネルのメモリーキャッシュに対する walker を提供しています。これらの walker は同じ init、step、および fini 関数を共有しているため、mdb_walker_twalk_init_arg メンバーを使用して、適切なキャッシュのアドレスを walk_arg として指定できます。

walker が mdb_layered_walk() を呼び出して配下の層をインスタンス化した場合、配下の層は walker の step 関数を呼び出す前に walk_addrwalk_layer をリセットします。配下の層は walk_addr を配下のオブジェクトのターゲットの仮想アドレスに設定し、walk_layer を配下のオブジェクトの walker のローカルコピーに設定します。階層化された walk については、以降の mdb_layered_walk() の説明を参照してください。

walker の init および step 関数は、次の状態値のどれかを返します。

WALK_NEXT

次のステップへ進む。walk init 関数が WALK_NEXT を返すと、MDB は walk step 関数を呼び出す。walk step 関数から WALK_NEXT が返されたときは、MDB がもう一度 step 関数を呼び出す必要があることを示す

WALK_DONE

walk が正常に完了した。WALK_DONE は、walk が完了したことを示すために step 関数から返される場合と、与えられたデータ構造体が空である場合などに step が不要であることを示すために init 関数から返される場合がある

WALK_ERR

walk がエラーのため終了した。WALK_ERR が init 関数から返された場合、mdb_walk() (またはそれに相当するもの) は -1 を返して、walker が初期化に失敗したことを示す。WALK_ERR が step 関数から返された場合、walk は終了するが、mdb_walk() 関数からは成功が返される

walk_callback からも、上記のどれかの値が返されます。したがって walk step 関数は次のオブジェクトのアドレスを決定し、このオブジェクトのローカルコピーを読み取って、walk_callback 関数を呼び出し、その状態を返します。walk が完了したか、またはエラーが発生した場合、step 関数もコールバックを呼び出さずに WALK_DONE または WALK_ERR を返すことがあります。

次に示すように、walker 自体は mdb_walker_t 構造体を使用して定義されます。

typedef struct mdb_walker {
			const char *walk_name;                 /* walk のタイプ名 */
			const char *walk_descr;                /* walk の記述 */
			int (*walk_init)(mdb_walk_state_t *);  /* walk コンストラクタ */
			int (*walk_step)(mdb_walk_state_t *);  /* walk イタレータ */
			void (*walk_fini)(mdb_walk_state_t *); /* walk デストラクタ */
			void *walk_init_arg;                   /* コンストラクタの引数 */
} mdb_walker_t;

walk_name および walk_descr フィールドは、それぞれ walker の名前と短い説明を含む文字列を指すように初期化されます。walker は NULL 以外の名前と説明を持つ必要があり、名前には MDB メタキャラクタを入れることはできません。説明の文字列は ::walkers および ::dmods 組み込み dcmd によって出力されます。

walk_initwalk_step、および walk_fini メンバーは、前述のように walk 関数自体を指しています。特別な初期化またはクリーンアップ措置が必要でないことを示すには、walk_init および walk_fini メンバーを NULL に設定します。

walk_step メンバーは NULL には設定できません。前述のように、walk_init_arg メンバーは、指定された walker に対して新規に作成された mdb_walk_state_t ごとに walk_arg メンバーを初期化するのに使用されます。一般的な walker の各ステップについては、図 7-1 を参照してください。

図 7-1 walker の例

Graphic

walker はカーネル内の proc_t 構造体のリストに対して繰り返すように設計されています。リストの先頭は practive 大域変数に格納されており、各要素の p_next ポインタはリスト内の次の proc_t を指しています。リストの末尾は NULL ポインタになっています。ステップ (1) で walker の init ルーチン、practive のシンボルは mdb_lookup_by_name() を使用して検出され、この値が wsp の指す mdb_walk_state_t にコピーされます。

walker の step 関数では、ステップ (2) としてリスト内の次の proc_t 構造体が mdb_vread() を使用してデバッガのアドレス空間にコピーされます。ステップ (3) でこのローカルコピーを指すポインタによってコールバック関数が起動され、mdb_walk_state_t が次の繰り返しに対する proc_t 構造体のアドレスで更新されます。ステップ (4) では、この更新は、リスト内の次の要素を指す次のポインタに対応しています。

これらのステップは一般的な walker の構造を示しています。init ルーチンが特定のデータ構造体に関するグローバルな情報を検出し、step 関数が次のデータ項目のコピーを読み取ってコールバック関数に渡し、次の要素のアドレスが読み取られます。最終的に walk が終了すると、fini 関数によってすべての専用記憶領域が解放されます。

API 関数

mdb_pwalk()

int mdb_pwalk(const char *name, mdb_walk_cb_t func, void *data, uintptr_t addr);

name で指定された walker を使用して addr から始まるローカル walk を開始し、各ステップでコールバック関数 func を呼び出します。addr が NULL の場合、グローバル walk が実行されます。mdb_pwalk() を呼び出すことは addr パラメタを追跡せずに mdb_walk() を呼び出すことと同じです。この関数は成功した場合 0 を、エラーの場合 -1 を返します。walker 自体が致命的なエラーを返した場合、または指定された walker 名がデバッガに認識されない場合、mdb_pwalk() 関数は失敗します。walker 名に重複があった場合、逆引用符 (`) 演算子を使用して名前の有効範囲を指定できます。data パラメタは、呼び出し元にだけ意味を持つ隠された引数です。このパラメタは walk の各ステップで func に戻されます。

mdb_walk()

int mdb_walk(const char *name, mdb_walk_cb_t func, void *data);

name で指定された walker を使用して addr から始まるグローバル walk を開始し、各ステップでコールバック関数 func を起動します。この関数は成功した場合 0 を、エラーの場合 -1 を返します。walker 自体が致命的なエラーを返した場合、または指定された walker 名がデバッガに認識されない場合、mdb_walk() 関数は失敗します。walker 名に重複があった場合、逆引用符 (`) 演算子を使用して名前の有効範囲を指定できます。data パラメタは、呼び出し元にだけ意味を持つ隠された引数です。このパラメタは walk の各ステップで func に戻されます。

mdb_pwalk_dcmd()

int mdb_pwalk_dcmd(const char *wname, const char *dcname, int argc,
			const mdb_arg_t *argv, uintptr_t addr);

wname で指定された walker を使用して addr から始まるローカル walk を開始し、各ステップで argc および argv を指定して、dcname で指定された dcmd を起動します。この関数は成功した場合 0 を、エラーの場合 -1 を返します。walker 自体が致命的なエラーを返した場合、指定された walker 名または dcmd 名がデバッガに認識されない場合、あるいは dcmd 自体が walker に DCMD_ABORT または DCMD_USAGE を返した場合、この関数は失敗します。名前の重複があった場合、walker 名と dcmd 名は逆引用符 (`) 演算子を使用して名前の有効範囲を指定できます。mdb_pwalk_dcmd() から起動された場合、dcmd はフラグパラメタに DCMD_LOOP および DCMD_ADDRSPEC ビットを設定し、最初の呼び出しで DCMD_LOOPFIRST が設定されます。

mdb_walk_dcmd()

int mdb_walk_dcmd(const char *wname, const char *dcname, int argc,
			const mdb_arg_t *argv);

wname で指定された walker を使用してグローバル walk を開始し、各ステップで argc および argv を指定して、dcname で指定された dcmd を起動します。この関数は成功した場合 0 を、エラーの場合 -1 を返します。walker 自体が致命的なエラーを返した場合、指定された walker 名または dcmd 名がデバッガに認識されない場合、あるいは dcmd 自体が walker に DCMD_ABORT または DCMD_USAGE を返した場合、この関数は失敗します。名前の重複があった場合、walker 名と dcmd 名は逆引用符 (`) 演算子を使用して名前の有効範囲を指定できます。mdb_walk_dcmd() から起動された場合、dcmd はフラグパラメタに DCMD_LOOP および DCMD_ADDRSPEC ビットを設定し、最初の呼び出しで DCMD_LOOPFIRST が設定されます。

mdb_call_dcmd()

int mdb_call_dcmd(const char *name, uintptr_t addr, uint_t flags, 
			int argc, const mdb_arg_t *argv);

与えられたパラメタで指定された dcmd 名を起動します。ドット変数が addr にリセットされ、addrflagsargc、および argv が dcmd に渡されます。この関数は成功した場合 0 を、エラーの場合 -1 を返します。dcmd が DCMD_ERRDCMD_ABORT、または DCMD_USAGE を返した場合、あるいは指定された dcmd 名がデバッガに認識されない場合、この関数は失敗します。名前の重複があった場合、dcmd 名は逆引用符 (`) 演算子を使用して名前の有効範囲を指定できます。

mdb_layered_walk()

int mdb_layered_walk(const char *name, mdb_walk_state_t *wsp);

wsp で指定された walk を、指定された walker 名を使用して開始された walk の上の層に置きます。名前の重複があった場合、dcmd 名は逆引用符 (`) 演算子を使用して名前の有効範囲を指定できます。階層化された walk を使用すると、他のデータ構造体に組み込まれたデータ構造体に対する walker を簡単に作成することができます。

たとえば、カーネルの各 CPU 構造体に組み込み構造体を指すポインタが含まれているとします。組み込み構造体タイプに対する walker を作成するときに、CPU 構造体を繰り返すコードを複製して各 CPU 構造体の該当するメンバーの参照を解除することもできますが、組み込み構造体の walker を既存の CPU walker の上に重ねることもできます。

mdb_layered_walk() 関数は、現在の walk に新規の層を追加するために walker の init ルーチンの中から使用されます。配下の層は mdb_layered_walk() の呼び出しの一部として初期化されます。呼び出し元の walk ルーチンは、現在の walk の状態を指すポインタを渡します。この状態を使用して階層化された walk が構築されます。階層化された各 walk は、呼び出し元の walk fini 関数が呼び出された後、クリーンアップされます。複数の層が walk に追加されている場合、呼び出し元の walk step 関数は最初の層から返された各要素を処理した後、次に 2 番目の層へ進み、以降も同様に処理します。

mdb_layered_walk() 関数は成功した場合 0 を、エラーの場合 -1 を返します。指定された walker 名がデバッガに認識されない場合、wsp ポインタが有効かつアクティブな walk 状態ポインタでない場合、階層化された walker 自体が初期化に失敗した場合、または呼び出し元が自分自身の上に walker を重ねようとした場合、この関数は失敗します。

mdb_add_walker()

int mdb_add_walker(const mdb_walker_t *w);

新規の walker をデバッガに登録します。walker は、「dcmd と walker の名前解決」に説明されている名前解決規則に従って、モジュールの名前空間、およびデバッガのグローバルな名前空間に追加されます。この関数は成功した場合 0 を返しますが、指定された walker 名が既にこのモジュールによって登録済みであったり、walker の構造体 w が正しく構築されていなかったりした場合、エラーとして -1 を返します。mdb_walker_t w の情報が内部のデバッガ構造体にコピーされるため、呼び出し元では mdb_add_walker() を呼び出した後にこの構造体を再使用または解放できます。

mdb_remove_walker()

int mdb_remove_walker(const char *name);

指定された name の walker を削除します。この関数は成功した場合 0 を、エラーの場合 -1 を返します。walker は現在のモジュールの名前空間から削除されます。walker 名が認識されない場合や、別のモジュールの名前空間だけに登録されている場合、この関数は失敗します。mdb_remove_walker() 関数を使用すると、mdb_add_walker() を使用して動的に追加された walker、またはモジュールのリンク構造の一部として静的に追加された walker を削除することができます。walker 名の有効範囲を指定する演算子は、ここでは使用できません。mdb_remove_walker() の呼び出し元が、別のモジュールからエクスポートされた walker を削除しようとしても無効です。

mdb_vread() および mdb_vwrite()

ssize_t mdb_vread(void *buf, size_t nbytes, uintptr_t addr);
ssize_t mdb_vwrite(const void *buf, size_t nbytes, uintptr_t addr);

これらの関数は、addr パラメタで指定された、所定のターゲットの仮想アドレスからデータを読み取ったり、そのアドレスにデータを書き込んだりするのに使用します。mdb_vread() 関数は成功した場合 nbytes を、エラーの場合 -1 を返します。指定されたアドレスからデータの一部しか読み取れなかったためにデータが切り捨てられた場合、-1 が返されます。mdb_vwrite() 関数は成功した場合、実際に書き込まれたバイト数を返し、エラーが発生した場合は -1 を返します。

mdb_pread() および mdb_pwrite()

ssize_t mdb_pread(void *buf, size_t nbytes, uint64_t addr);
ssize_t mdb_pwrite(const void *buf, size_t nbytes, uint64_t addr);

これらの関数は、addr パラメタで指定された、所定のターゲット物理アドレスからデータを読み取ったり、そのアドレスにデータを書き込んだりするのに使用します。mdb_pread() 関数は成功した場合 nbytes を、エラーの場合 -1 を返します。指定されたアドレスからデータの一部しか読み取れなかったためにデータが切り捨てられた場合、-1 が返されます。mdb_pwrite() 関数は成功した場合、実際に書き込まれたバイト数を返し、エラーが発生した場合は -1 を返します。

mdb_readstr()

ssize_t mdb_readstr(char *s, size_t nbytes, uintptr_t addr);

mdb_readstr() 関数は、ターゲットの仮想アドレス addr から始まる NULL で終了する C 文字列を、s で指定されたバッファに読み込みます。バッファのサイズは nbytes で指定されます。この文字列が長すぎてバッファに収まらない場合、文字列はバッファサイズで切り捨てられ、s[nbytes - 1] に NULL バイトが格納されます。成功した場合、末尾の NULL バイトを含めずに s に格納された文字列の長さが返され、失敗した場合はエラーを示す -1 が返されます。

mdb_writestr()

ssize_t mdb_writestr(const char *s, uintptr_t addr);

mdb_writestr() 関数は、NULL で終了する C 文字列を末尾の NULL バイトも含めて s から、ターゲットの仮想アドレス空間の addr で指定されたアドレスに書き込みます。成功した場合、末尾の NULL バイトを含めずに実際に書き込まれたバイト数が返され、失敗した場合はエラーを示す -1 が返されます。

mdb_readsym()

ssize_t mdb_readsym(void *buf, size_t nbytes, const char *name);

読み取りが開始される仮想アドレスが name で指定されたシンボルの値から取得される点以外は、mdb_readsym()mdb_vread() に似ています。その名前でシンボルが見つからなかった場合、または読み取りエラーが発生した場合は -1 が返されます。成功した場合は nbytes が返されます。

シンボルの検索の失敗と読み取りの失敗を区別する必要がある場合、呼び出し元ではまずシンボルを別に調べます。一次実行可能ファイルのシンボルテーブルを使用してシンボルが検索されます。シンボルが別のシンボルテーブルに存在する場合、最初に mdb_lookup_by_obj()、次に mdb_vread() の順で適用する必要があります。

mdb_writesym()

ssize_t mdb_writesym(const void *buf, size_t nbytes, const char *name);

mdb_writesym() は、書き込みが開始される仮想アドレスが name で指定されたシンボルの値から取得される点以外は、mdb_vwrite() と同じです。その名前でシンボルが見つからなかった場合は -1 が返されます。それ以外の場合、成功すると正常に書き込まれたバイト数が返され、エラーが発生すると -1 が返されます。一次実行可能ファイルのシンボルテーブルを使用してシンボルが検索されます。シンボルが別のシンボルテーブルに存在する場合、最初に mdb_lookup_by_obj()、次に mdb_vwrite() の順で適用する必要があります。

mdb_readvar() および mdb_writevar()

ssize_t mdb_readvar(void *buf, const char *name);
ssize_t mdb_writevar(const void *buf, const char *name);

読み取りが開始される仮想アドレスと読み取るバイト数が name で指定されたシンボルの値とサイズから取得される点以外は、mdb_readvar()mdb_vread() に似ています。その名前でシンボルが見つからなかった場合は -1 が返されます。成功するとシンボルのサイズ、すなわち正常に読み取られたバイト数が返され、エラーが発生すると -1 が返されます。たとえば次のように、この関数はサイズの固定している既知の変数を読み取る場合に有用です。


int hz; 	/* システムクロックレート */
mdb_readvar(&hz, "hz");

シンボルの検索の失敗と読み取りの失敗を区別する必要がある場合、呼び出し元ではまずシンボルを別に調べます。また、ローカルの宣言がターゲットの定義とまったく同じであることを確認するために、呼び出し元では当該のシンボルの定義を注意して調べる必要があります。たとえば、呼び出し元が int を宣言しているのに当該のシンボルが実際には long であったため、デバッガが 64 ビットのカーネルターゲットを調べている場合、mdb_readvar() は 8 バイトを呼び出し元のバッファに戻すため、int に格納される分の後に残る 4 バイトが破壊されてしまいます。

書き込みが開始される仮想アドレスと書き込むバイト数が name で指定されたシンボルの値とサイズから取得される点以外は、mdb_writevar()mdb_vwrite()と同じです。その名前でシンボルが見つからなかった場合は -1 が返されます。成功すると正常に書き込まれたバイト数が返され、エラーが発生すると -1 が返されます。

どちらの関数も、シンボルの検索では一次実行可能ファイルのシンボルテーブルが使用されます。シンボルが別のシンボルテーブルに存在する場合、最初に mdb_lookup_by_obj()、次に mdb_vread() または mdb_vwrite() の順で適用する必要があります。

mdb_lookup_by_name() および mdb_lookup_by_obj()

int mdb_lookup_by_name(const char *name, GElf_Sym *sym);
int mdb_lookup_by_obj(const char *object, const char *name, GElf_Sym *sym);

指定されたシンボル名を検索し、ELF シンボル情報を sym の指す GElf_Sym にコピーします。シンボルが見つかった場合、この関数は 0 を返します。それ以外の場合は -1 を返します。name パラメタはシンボル名を指定します。object パラメタは、デバッガにシンボルを検索する場所を指示します。mdb_lookup_by_name() 関数では、オブジェクトファイルは MDB_OBJ_EXEC にデフォルト設定されます。mdb_lookup_by_obj() では、オブジェクト名は次のどれかになります。

MDB_OBJ_EXEC

実行可能ファイルのシンボルテーブル (.symtab セクション) を検索します。カーネルクラッシュダンプの場合、このテーブルは unix.X ファイルまたは /dev/ksyms のシンボルテーブルに相当します。

MDB_OBJ_RTLD

実行時リンカーのシンボルテーブルを検索します。カーネルクラッシュダンプの場合、このテーブルは krtld モジュールのシンボルテーブルに相当します。

MDB_OBJ_EVERY

すべての既知のシンボルテーブルを検索します。カーネルクラッシュダンプの場合、この中には unix.X ファイルまたは /dev/ksyms.symtab および .dynsym セクションのほか、モジュール単位のシンボルテーブルが処理されていればそれらのテーブルも含まれます。

object

特定のロードオブジェクト名が明示的に指定されている場合、検索はこのオブジェクトのシンボルテーブルだけに限定されます。オブジェクトは、「シンボルの名前解決」に説明されているロードオブジェクトのための命名規則に従って命名されます。

mdb_lookup_by_addr()

int mdb_lookup_by_addr(uintptr_t addr, uint_t flag, char *buf,
				size_t len, GElf_Sym *sym);

指定されたアドレスに対応するシンボルを検索し、ELF シンボル情報を sym の指す GElf_Sym に、シンボル名を buf で指定された文字配列にコピーします。対応するシンボルが見つかった場合、この関数は 0 を返します。見つからない場合は -1 を返します。

flag パラメタは検索モードを指定するもので、次のどれかになります。

MDB_SYM_FUZZY

現在のシンボルディスタンスの設定に基づいて、あいまい一致検索を実行できます。シンボルディスタンスは、::set -s 組み込みコマンドを使用して制御することができます。シンボルディスタンスが明示的に設定されている場合、すなわち絶対モードの場合、シンボルの値からアドレスまでの距離が絶対シンボルディスタンスを超えなければ、アドレスはシンボルと一致します。スマートモードが有効な場合、すなわちシンボルディスタンス = 0 の場合、アドレスが有効範囲内、すなわちシンボルの値からシンボルの値 + シンボルのサイズまでの範囲であればシンボルと一致します。

MDB_SYM_EXACT

あいまい一致検索を許可しません。シンボル値が指定されたアドレスと厳密に等しい場合だけ、シンボルはアドレスと一致します。

シンボルが一致すると、シンボル名が呼び出し元の提供した buf にコピーされます。len パラメタはこのバッファの長さをバイト単位で指定します。呼び出し元の buf は、少なくとも MDB_SYM_NAMLEN バイト必要です。デバッガはシンボル名をこのバッファにコピーし、後ろに NULL の 1 バイトを追加します。名前の長さがバッファの長さを超えると、シンボル名は切り捨てられますが、末尾には常に NULL の 1 バイトが存在します。

mdb_getopts()

int mdb_getopts(int argc, const mdb_arg_t *argv, ...);

指定された引数の配列 (argv) からオプションとオプションの引数を構文解析し、処理します。argc パラメタは引数配列の長さを示します。この関数は各引数を順に処理し、処理できない引数があると停止して、その配列の索引を返します。すべての引数が正常に処理できた場合、argc を返します。

argc および argv パラメタの後に、mdb_getopts() 関数では、argv 配列に入る予定のオプションを記述した可変の引数リストを指定できます。各オプションはオプション文字 (char 引数)、オプションタイプ (uint_t 引数)、および次の表に示すような 1 つまたは 2 つのその他の引数で記述されます。オプション引数のリストの末尾は NULL 引数となっています。タイプは次のどれかです。

MDB_OPT_SETBITS

指定されたビットとフラグワードとの論理和をとります。このオプションは次のパラメタで記述されます。

char c, uint_t type, uint_t bits, uint_t *p

タイプが MDB_OPT_SETBITS であり、argv リストでオプション c が検出された場合、デバッガはポインタ p の参照する整数と指定ビットの論理和をとります。

MDB_OPT_CLRBITS

指定されたビットをフラグワードから消去します。このオプションは次のパラメタで記述されます。

char c, uint_t type, uint_t bits, uint_t *p

タイプが MDB_OPT_CLRBITS であり、argv リストでオプション c が検出された場合、デバッガはポインタ p の参照する整数から指定ビットを消去します。

MDB_OPT_STR

文字列引数をとります。このオプションは次のパラメタで記述されます。

char c, uint_t type, const char **p

タイプが MDB_OPT_STR であり、argv リストでオプション c が検出された場合、デバッガは c の後に続く文字列引数を指すポインタを p の参照しているポインタに格納します。

MDB_OPT_UINTPTR

uintptr_t 引数をとります。このオプションは次のパラメタで記述されます。

char c, uint_t type, uintptr_t *p

タイプが MDB_OPT_UINTPTR であり、argv リストでオプション c が検出された場合、デバッガは c の後に続く整数引数を p の参照している uintptr_t に格納します。

MDB_OPT_UINT64

uint64_t 引数をとります。このオプションは次のパラメタで記述されます。

char c, uint_t type, uint64_t *p

タイプが MDB_OPT_UINT64 であり、argv リストでオプション c が検出された場合、デバッガは c の後に続く整数引数を p の参照している uint64_t に格納します。

たとえば、次のソースコードは、dcmd で mdb_getopts() を使用して、opt_v 変数を TRUE に設定するブール型オプション "-v"、および opt_s 変数に格納されている文字列引数をとるオプション "-s" をとる方法を示しています。

int
dcmd(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
{
        uint_t opt_v = FALSE;
        const char *opt_s = NULL;

        if (mdb_getopts(argc, argv,
            'v', MDB_OPT_SETBITS, TRUE, &opt_v,
            's', MDB_OPT_STR, &opt_s, NULL) != argc)
                return (DCMD_USAGE);

        /* ... */
}
また、mdb_getopts() 関数は、呼び出し元に戻る前に無効なオプション文字やオプション引数の欠落を検出すると、自動的に警告メッセージを表示します。引数文字列および argv 配列のための記憶領域は、dcmd が完了するとデバッガにより自動的にガベージコレクションに集められます。

mdb_strtoull()

u_longlong_t mdb_strtoull(const char *s);

指定された文字列 s符号なし long long 表現に変換します。この関数は、mdb_getopts() が適当でない状況において文字列引数を処理し変換します。文字列引数が有効な整数表現に変換できない場合、関数は失敗し、該当するエラーメッセージが出力され、dcmd は異常終了します。したがって、エラーチェックコードは不要です。文字列には、先頭に有効な指示子 (0i、0I、0o、0O、0t、0T、0x、または 0X) を付けることができますが、付けない場合はデフォルトを使用するものと解釈されます。s の中に基底文字として適切でない文字があったり、整数のオーバーフローが発生したりすると、この関数は失敗し、dcmd は異常終了します。

mdb_alloc()mdb_zalloc() および mdb_free()

void *mdb_alloc(size_t size, uint_t flags);
void *mdb_zalloc(size_t size, uint_t flags);
void mdb_free(void *buf, size_t size);

mdb_alloc()size バイトのデバッガメモリーを割り当て、割り当てたメモリーにポインタを返します。割り当て済みメモリーは、どのような C 構造体でも保持できるように、少なくともダブルワードが割り当てられます。それ以上の割り当てはできません。flags パラメタは、次の 1 つ以上の値のビット単位の論理和となります。

UM_NOSLEEP

要求を満たすだけの十分なメモリーがすぐに使用可能でない場合、失敗を示す NULL が返されます。呼び出し元は NULL が返されたかどうかをチェックして、NULL の場合には適切に対処する必要があります。

UM_SLEEP

要求を満たすだけの十分なメモリーがすぐに使用可能でない場合、要求を満たすことができるまでの間、スリープ (休眠) します。したがって、UM_SLEEP 割り当ての場合、成功することが保証されています。呼び出し元で NULL 戻り値をチェックする必要はありません。

UM_GC

このデバッガコマンドの終わりに自動的に割り当てのガベージコレクションを行います。割り当ての解除はデバッガによって自動的に行われるので、呼び出し元はこのブロックにおいてそれ以降 mdb_free() を呼び出すことはできません。dcmd がユーザーによって中断された場合、デバッガが不要メモリーのガベージコレクションを実行できるように、dcmd の中からメモリーの割り当てを行うときは、必ず UM_GC を使用する必要があります。

mdb_zalloc()mdb_alloc() と似ていますが、呼び出し元に戻る前に割り当てたメモリーにはゼロが入ります。mdb_alloc() から戻されるメモリーの初期内容は、保証されません。mdb_free() は、UM_GC で割り当てられたメモリー以外の、以前に割り当て済みのメモリーを解放するのに使用します。バッファアドレスとサイズは元の割り当てと正確に一致している必要があります。mdb_free() を使用して割り当ての一部だけを解放することはできません。また、二度以上割り当てを解放することもできません。ゼロバイトの割り当てでは、常に NULL が返されます。サイズがゼロの NULL ポインタの解放は、常に成功します。

mdb_printf()

void mdb_printf(const char *format, ...);

指定された書式文字列と引数を使用して、書式付き出力を書き出します。警告とエラーメッセージを除いて、モジュール作成者はあらゆる出力に対して mdb_printf() を使用する必要があります。この関数は必要に応じて自動的に組み込み出力ページャをトリガーします。mdb_printf() 関数は printf(3C) に似ていますが、次のような例外があります。ワイド文字列に対して %C%S、および %ws 指示子はサポートされていない、%f 浮動小数点形式がサポートされていない、代替ダブルフォーマットに対する %e%E%g、および%G 指示子では、単一形式の出力だけが生成される、書式 %.n の精度の指定はサポートされていない。サポートされている指示子のリストを次に示します。

フラグ指示子

%#

書式文字列の中に # 記号があった場合、与えられたフォーマットの代替書式を選択します。すべてのフォーマットに代替書式があるとは限りません。代替書式はフォーマットによって異なります。代替書式の詳細については、以降のフォーマットの説明を参照してください。

%+

符号付きの値を出力する場合、常に符号として '+' または '-' の接頭辞を表示します。%+ を指定しない場合、正の値には符号の接頭辞が付かず、負の値には先頭に '-' の接頭辞が付けられます。

%-

指定されたフィールド幅の中で出力を左詰めにします。出力の幅が指定されたフィールド幅より小さい場合、右側には空白文字が入ります。%- を指定しない場合、デフォルトの設定では値は右詰めになります。

%0

出力が右詰めで出力幅が指定されたフィールドの幅より小さい場合、出力フィールドがゼロで埋められます。%0 を指定しない場合、右詰めにした値の前の残りのフィールドには空白文字が入ります。

フィールド幅の指示子

%n

フィールド幅は指定された 10 進数値に設定されます。

%?

フィールド幅は 16 進数のポインタ値の最大幅に設定されます。この値は ILP32 環境では 8、LP64 環境では 16 です。

%*

フィールド幅は引数リストの現在の位置で指定された値に設定されます。この値は int であるとみなされます。64 ビットのコンパイル環境では、long 値を int にキャストしなければならない場合があります。

整数指示子

%h

short 型の整数値が出力されます。

%l

long 型の整数値が出力されます。

%ll

long long 型の整数値が出力されます。

端末属性指示子

デバッガの標準出力が端末であり、terminfo データベースから端末属性を変更できる場合、次の端末エスケープコンストラクトが使用できます。

%<n>

n に対応する端末属性を有効にします。%<> の各インスタンスごとに、1 つの属性だけを有効にできます。

%</n>

n に対応する端末属性を無効にします。反転表示、選択不可テキスト、およびボールドテキストの場合、これらの属性を無効にする端末コードは同じである可能性があります。したがって、これらの属性を互いに独立して無効にはできない場合があります。

端末情報が使用できない場合、各端末属性コンストラクトは mdb_printf() で無視されます。端末属性については、terminfo(4) のマニュアルページを参照してください。使用可能な terminfo 属性は次のとおりです。

a

代替文字セット

b

ボールドテキスト

d

選択不可テキスト

r

反転表示

s

強調表示機能

u

下線

書式指示子

%%

'%' 記号が出力されます。

%a

アドレスが記号形式で出力されます。%a に関連付けられている値の最小サイズは uintptr_t ですが、%la の指定は必須ではありません。アドレスからシンボルへの変換が有効な場合、デバッガはアドレスを現在の出力の基数でのシンボル名とそれに続くオフセットに変換して、この文字列を出力しようとします。変換が有効でない場合、アドレス値はデフォルトの出力の基数で出力されます。%#a を使用した場合、代替書式によって出力に ':' 接尾辞が付加されます。

%A

この書式は %a と同じですが、アドレスがシンボル名とオフセットに変換できない場合は何も出力されない点が異なっています。%#A を使用した場合、アドレス変換が失敗したとき、代替書式によって '?' が出力されます。

%b

ビットフィールドを記号書式で復号化し、出力します。この指示子は 2 つの連続する引数をとります。この 2 つの引数はビットフィールド値 (%b に対する int%lb に対する long など) および mdb_bitmask_t 構造体の配列を指すポインタです。


typedef struct mdb_bitmask {
		const char *bm_name;       /* 出力する文字列名 */
		u_longlong_t bm_mask;      /* ビットのマスク */
		u_longlong_t bm_bits;      /* 値とマスクの結果 */
} mdb_bitmask_t;

配列の末尾は bm_name フィールドが NULL に設定されている構造体でなければなりません。%b を使用した場合、デバッガは値の引数を読み取り、各 mdb_bitmask 構造体を繰り返して、次の条件をチェックします。


(value & bitmask->bm_mask) == bitmask->bm_bits

この式が真の場合、bm_name 文字列が出力されます。各文字列はコンマで区切って出力されます。次の例は、%b を使用して kthread_tt_flag フィールドを復号化する方法を示しています。


const mdb_bitmask_t t_flag_bits[] = {
		{ "T_INTR_THREAD", T_INTR_THREAD, T_INTR_THREAD },
		{ "T_WAKEABLE", T_WAKEABLE, T_WAKEABLE },
		{ "T_TOMASK", T_TOMASK, T_TOMASK },
		{ "T_TALLOCSTK", T_TALLOCSTK, T_TALLOCSTK },
			...
		{ NULL, 0, 0 }
};

void
thr_dump(kthread_t *t)
{
		mdb_printf("t_flag = <%hb>¥n", t->t_flag, t_flag_bits);

		...
}

t_flag が 0x000a に設定されている場合、この関数によって次のように出力されます。


t_flag = <T_WAKEABLE,T_TALLOCSTK>

%c

指定された整数を ASCII 文字として出力します。

%d

指定された整数を符号付き 10 進数値として出力します。%i と同じです。

%e

指定された倍精度数を浮動小数点形式 [+/-]d.ddddddde[+/-]dd で出力します。小数点の前が 1 桁、小数点以下が 7 桁で、指数の後は少なくとも 2 桁です。

%E

指定された倍精度数を %e と同じ規則を使用して出力しますが、指数文字として 'e' ではなく 'E' を使用する点が異なっています。

%g

指定された倍精度数を %e と同じ浮動小数点形式で出力しますが、16 桁を使用します。%llg を指定した場合、引数の型は 4 倍精度浮動小数点数の long double となります。

%G

指定された倍精度数を %g と同じ規則を使用して出力しますが、指数文字として 'e' ではなく 'E' を使用する点が異なっています。

%i

指定された整数を符号付き 10 進数値として出力します。%d と同じです。

%I

指定された 32 ビット符号なし整数をドット付き 10 進形式のインターネット IPv4 アドレスとして出力します。たとえば、16 進数値の 0xffffffff255.255.255.255 として出力されます。

%m

空白のマージンを印刷します。フィールドを指定しないと、デフォルトの出力マージン幅が使用されます。フィールド幅を指定すると、フィールド幅によって出力される空白の文字数が決定されます。

%o

指定された整数を符号なし 8 進数値として出力します。%#o を使用した場合、代替書式によって出力の先頭に '0' が付けられます。

%p

指定されたポインタ (void *) を 16 進数値として出力します。

%q

指定された整数を符号付き 8 進数値として出力します。%#o を使用した場合、代替書式によって出力の先頭に '0' が付けられます。

%r

指定された整数を現在の出力の基数での符号なし値として出力します。ユーザーは $d dcmd を使用して出力の基数を変更することができます。%#r を指定すると、代替書式によって値の先頭に該当する基底接頭辞が付けられます。2 進数の場合 '0i'、8 進数の場合 '0o'、10 進数の場合 '0t'、16 進数の場合 '0x'。

%R

指定された整数を現在の出力の基数で符号付きの値として出力します。%#R を指定すると、代替書式によって値の先頭に該当する基底接頭辞が付けられます。

%s

指定された文字列 (char *) を出力します。文字列のポインタが NULL の場合、文字列 '<NULL>' が出力されます。

%t

1 つまたは複数のタブストップ分出力され、幅を指定しないと次のタブストップまで出力され、幅を指定するとフィールド幅によって出力されるタブストップの数が決定されます。

%T

カラムをフィールド幅の倍数分出力します。フィールド幅を指定しないと、何の処理も実行されません。現在出力されているカラムがフィールド幅の倍数でない場合、空白が付加されてカラムが出力されます。

%u

指定された整数を符号なし 10 進数値として出力します。

%x

指定された整数を 16 進数値として出力します。10 から 15 までの値を表す数字として、a から f までの文字を使用します。%#X を指定すると、代替書式によって値の先頭に '0x' が付けられます。

%X

指定された整数を 16 進数値として出力します。10 から 15 までの値を表す数字として、A から F までの文字を使用します。%#x を指定すると、代替書式によって値の先頭に '0X' が付けられます。

%Y

指定された time_t を文字列 'year month day HH:MM:SS' として出力します。

mdb_snprintf()

size_t mdb_snprintf(char *buf, size_t len, const char *format, ...);

指定された書式文字列と引数に基づいて書式付き文字列を作成し、作成した文字列を指定された buf に格納します。mdb_snprintf() 関数は mdb_printf() 関数と同じ書式指示子と引数をとります。len パラメタは buf のサイズをバイト単位で指定します。フォーマットされた len - 1 バイト以下のバイトが buf に格納されます。mdb_snprintf() では、常に buf の末尾は NULL 1 バイトで終了します。この関数は、末尾の NULL のバイトを除外した、完全な書式付き文字列に必要なバイト数を返します。buf パラメタが NULL で len がゼロに設定されている場合、buf には何も格納されず、完全な書式付き文字列に必要なバイト数が返されます。この方法を使用して、動的メモリー割り当て用のバッファの適切なサイズが決定されます。

mdb_warn()

void mdb_warn(const char *format, ...);

エラーまたは警告メッセージを標準エラーに出力します。mdb_warn() 関数では、書式文字列と mdb_printf() で掲げられているすべての指示子を含む可変の引数リストを指定することができます。ただし、mdb_warn() の出力が標準エラーに送られる場合は、バッファには格納されず、出力ページャを通して送信されたり、dcmd パイプラインの一部として処理されることはありません。すべてのエラーメッセージには、自動的に先頭に "mdb:" という接頭辞が付けられます。

さらに、format パラメタには復帰改行 (¥n) 文字は含まれず、書式文字列の先頭には暗黙的に文字列 ": %s¥n" が付けられます。 ここで、%s は、モジュール API 関数が最後に記録したエラーに対応するエラーメッセージ文字列に置換されます。たとえば、次のソースコードの場合を考えます。


if (mdb_lookup_by_name("no_such_symbol", &sym) == -1)
				mdb_warn("lookup_by_name failed");

この場合、次のような出力が生成されます。

mdb: lookup_by_name failed: unknown symbol name

mdb_flush()

void mdb_flush(void);

現在バッファ化されているすべての出力をフラッシュします。通常、mdb の標準出力はラインバッファに格納されます。mdb_printf() で生成された出力は、復帰改行文字を見つけるまで、あるいは現在の dcmd の終わりまで、端末または他の標準出力の出力先にフラッシュされません。しかし、状況によっては、復帰改行を出力する前に標準出力を明示的にフラッシュする必要がある場合もあります。そのような場合にこの mdb_flush() 関数が使用できます。

mdb_one_bit()

const char *mdb_one_bit(int width, int bit, int on);

mdb_one_bit() 関数を使用して、関連のある 1 つのビットをオンまたはオフにして、ビットフィールドを図式化して出力することができます。この関数は snoop(1M) -v を使用して出力する場合と同様に、ビットフィールドを詳細に表示するのに有用です。たとえば、次のソースコードの場合を考えます。

#define FLAG_BUSY       0x1

uint_t flags;

/* ... */

mdb_printf("%s = BUSY¥n", mdb_one_bit(8, 0, flags & FLAG_BUSY));

次のような出力が得られます。

.... ...1 = BUSY

4 ビットごとに空白で区切られ、ビットフィールドの各ビットがピリオド (.) として出力されます。on パラメタの設定に従って、関連のあるビットは 1 または 0 で出力されます。ビットフィールドの合計の幅は width パラメタによりビット単位で指定し、関連のあるビットの位置は bit パラメタで指定します。ビットにはゼロから番号が付けられます。この関数はフォーマットされたビット表現を含む、適切なサイズの、NULL で終了する文字列を返します。現在の dcmd が完了すると、不要な文字列は自動的に回収されます。

mdb_inval_bits()

const char *mdb_inval_bits(int width, int start, int stop);

mdb_inval_bits() 関数は mdb_one_bit() と共に使用して、ビットフィールドを図式化して出力します。この関数は 、該当するビット位置に 'x' を表示することによって、そのビットを無効または予約済みとしてマーク付けします。ビットフィールドの各ビットはピリオド (.) として表現されますが、start および stop パラメタで指定された範囲のビット位置にあるビットは対象外です。ビットにはゼロから番号が付けられます。たとえば、次のソースコードの場合を考えます。

mdb_printf("%s = reserved¥n", mdb_inval_bits(8, 7, 7));

この場合、次のような出力が得られます。

x... .... = reserved

この関数はフォーマットされたビット表現を含む、適切なサイズの、NULL で終了する文字列を返します。現在の dcmd が完了すると、不要な文字列は自動的に回収されます。

mdb_inc_indent() および mdb_dec_indent()

ulong_t mdb_inc_indent(ulong_t n);
ulong_t mdb_dec_indent(ulong_t n);

これらの関数は、1 行出力する前に MDB によって空白で自動インデントされるカラム数を増減させます。デルタのサイズはカラム数、n で指定します。どちらの関数も前の絶対インデント値を返します。ゼロより小さい値にインデントを設定しようとしても無効です。どちらかの関数を呼び出した後に、mdb_printf() を呼び出すと、適切にインデントされています。dcmd が完了するか、ユーザーによって強制終了された場合、デバッガによってインデントは自動的にデフォルトの設定に戻ります。

mdb_eval()

int mdb_eval(const char *s);

指定されたコマンド文字列 s を、デバッガによって標準入力から読み取られたものとして、評価し実行します。この関数は成功すると 0 を返し、エラーが発生すると -1 を返します。コマンド文字列に構文エラーがあったり、mdb_eval() によって実行されたコマンド文字列がユーザーからのページャまたは割り込みの発生によって強制終了されたりすると、この関数は失敗します。

mdb_set_dot() および mdb_get_dot()

void mdb_set_dot(uintmax_t dot);
uintmax_t mdb_get_dot(void);

ドット ( "." 変数) の現在の値を設定するか、または取得します。モジュールを開発する上でドットの位置を再設定する必要があるのは、たとえば dcmd が前回読み取ったアドレスに続くアドレスを参照したままにしておく場合などです。

mdb_get_pipe()

void mdb_get_pipe(mdb_pipe_t *p);

現在の dcmd に対するパイプライン入力バッファの内容を取り出します。mdb_get_pipe() 関数は、dcmd で実行されますがパイプ入力要素ごとにデバッガから繰り返し呼び出されるのではなく、パイプ入力された要素全体を一度に呼び出して、一度だけ実行されます。mdb_get_pipe() がいったん呼び出されると、その dcmd は現在のコマンドの一部として再び起動されることはありません。これは、たとえば入力値のセットをソートする dcmd を作成するときに使用できます。

不要になったパイプの内容は、dcmd が完了すると配列の中に回収されます。この配列のポインタは p->pipe_data に格納されます。配列の長さは p->pipe_len に格納されます。dcmd がパイプラインの右側で実行されなかった場合、すなわちフラグパラメタで DCMD_PIPE フラグが設定されなかった場合、p->pipe_data は NULL に設定され、p->pipe_len はゼロに設定されます。

mdb_set_pipe()

void mdb_set_pipe(const mdb_pipe_t *p);

パイプラインの出力バッファをパイプ構造体 p によって記述された内容に設定します。パイプの値は配列 p->pipe_data に置かれ、配列の長さは p->pipe_len に格納されます。デバッガはこの情報の独自のコピーを作成するため、呼び出し元で必要に応じて p->pipe_data を解放する必要があります。パイプライン出力バッファが以前に空でなかった場合、その内容は新しい配列に格納されます。dcmd がパイプラインの左側で実行されなかった場合、すなわちフラグパラメタで DCMD_PIPE_OUT フラグが設定されなかった場合、この関数は無効です。

mdb_get_xdata()

ssize_t mdb_get_xdata(const char *name, void *buf, size_t nbytes);

name で指定されたターゲットの外部データバッファの内容を、buf で指定されたバッファの中に読み取ります。buf のサイズは nbytes パラメタで指定します。nbytes を超えるバイト数は呼び出し元のバッファにコピーされません。成功すると読み取った合計バイト数が返され、エラーが発生すると -1 が返されます。呼び出し元が、指定した特定のバッファのサイズを決定する必要がある場合は、buf を NULL に、nbytes をゼロに指定します。この場合、mdb_get_xdata() はバッファの合計サイズをバイト単位で返しますが、データは読み取りません。外部データバッファを使用することで、モジュールの作成者は、モジュール API を通して他の方法ではアクセスできないターゲットデータにアクセスすることができます。現在のターゲットによってエクスポートされた指定されたバッファのセットは、::xdata 組み込み dcmd を使用して参照できます。

その他の関数

さらに、モジュールの作成者は、次の string(3C) および bstring(3C) 関数も使用できます。これらの関数は、Solaris のマニュアルページに掲載されている関数と同じ意味を持っています。

strcat()           strcpy()                strncpy()
strchr()           strrchr()               strcmp()
strncmp()          strcasecmp()            strncasecmp()
strlen()           bcmp()                  bcopy()
bzero()            bsearch()               qsort()