スポンサーリンク

PTRACE(2) FreeBSD システムコールマニュアル PTRACE(2)

名称

ptrace − プロセスのトレースとデバッグ

ライブラリ

標準 C ライブラリ (libc, −lc)

書式

#include <sys/types.h>
#include <sys/ptrace.h>

int

ptrace(int request, pid_t pid, caddr_t addr, int data);

解説

ptrace() システムコールはトレースとデバッグの機能を提供します。これによっ て 1 つのプロセス (トレースするプロセス) が他のプロセス (トレースされるプ ロセス) を制御できます。トレースするプロセスは、最初にトレースされるプロ セスにアタッチしなければなりません。それから、そのプロセスの実行を制御す るために ptrace() システムコールを発行します。プロセスのメモリおよびレジ スタ状態へのアクセスも同様です。トレースするセッションの期間中、トレース されるプロセスはその親プロセス ID が (その結果の動作として) トレースする プロセスに ‘‘親を変更’’ されます。トレースするプロセスが同時に 1 つ以上の プロセスをアタッチすることは、許可されます。トレースするプロセスがその作 業を完了したときには、そのトレースされるプロセスをデタッチしなければなり ません。トレースするプロセスが最初にアタッチされている全てのプロセスをデ タッチせずに exit した場合には、それらのプロセスは kill されます。

ほとんどの場合、トレースされるプロセスは正常に実行されます。ただし、ト レースされるプロセスはシグナル (sigaction(2) を参照) を受信すると停止しま す。トレースするプロセスは、 wait(2) または SIGCHLD シグナルによってこれ を検知し、停止されたプロセスの状態を調査して、それを終了させるか、または 適切な形で実行を継続させます。そのシグナルは、トレースされるプロセスの動 作の結果として生成されたか、 kill(2) システムコールの使用による、通常のプ ロセスのシグナルかもしれません。もしくは、アタッチ、システムコール、また はトレースするプロセスによるステップの結果、トレースする仕組みによって生 成されたものかもしれません。トレースしているプロセスは、そのシグナルを使 用してプロセスの動作を観測するために (SIGTRAP の様に) そのシグナルを横取 りするか、もし適切であればそのシグナルをそのプロセスに転送するかを、選択 できます。 ptrace() システムコールは、これらすべてを制御するメカニズムで す。

request 引数は、どの操作を実行するかを指定します。残りの引数の意味は操作 によって異なります。後述する 1 つの特殊なケースを除いて、 ptrace() 呼び出 しはすべてトレースするプロセスによって行われ、 pid 引数はトレースされるプ ロセスのプロセス ID を指定します。 request 引数は次のものにできます。

       PT_TRACE_ME

この要求は、トレースされるプロセスが使用する唯一の要求で す。この要求は、プロセスがその親によってトレースされること を宣言します。他の引数はすべて無視されます (親プロセスが子 プロセスをトレースしない場合は、かなり混乱した結果になりま す。トレースされるプロセスが停止すると、このプロセスは、 ptrace() によってしか実行を継続できません)。プロセスがこの 要求を使用し、 execve(2) またはそれに組み込まれているルーチ ン (たとえば、 execv(3)) を呼び出した場合、そのプロセスは新 しいイメージの最初の命令を実行する前に停止します。また、実 行される実行可能モジュールの setuid または setgid ビットは 無視されます。

PT_READ_I, PT_READ_D
これらの要求は、トレースされるプロセスのアドレス空間から 1 つの int データを読み取ります。従来、 ptrace() は命令とデー タについて区別されたアドレス空間のあるマシンを許容していま した。これが 2 つの要求がある理由です。概念的には、 PT_READ_I が命令空間から読み取り、 PT_READ_D がデータ空間か ら読み取ります。現在の FreeBSD システムでは、これらの 2 つ の要求は完全に同一です。 addr 引数が、読取りが行われる (ト レースされるプロセスの仮想アドレス空間内の) アドレスを指定 します。このアドレスはどのような境界調整制約も満たす必要は ありません。読み取られた値は ptrace() からの戻り値として返 されます。

PT_WRITE_I, PT_WRITE_D
これらの要求は PT_READ_I および PT_READ_D と同様ですが、読 み取るのではなく書き込むところが異なります。 data 引数で書 き込まれる値を指定します。

PT_IO
この要求によって、トレースされるプロセスのアドレス空間内に ある任意量のデータの読取りと書込みが有効となります。 addr 引数は、以下のように定義される struct ptrace_io_desc へのポ インタを指定します。

struct ptrace_io_desc {

int

piod_op;

/* I/O 操作 */

void

*piod_offs;

/* 子オフセット */

void

*piod_addr;

/* 親オフセット */

size_t

piod_len;

/* 要求の長さ */

};

/*
* piod_op で指定される操作
*/

#define PIOD_READ_D

1

/* データ空間からの読取り */

#define PIOD_WRITE_D

2

/* データ空間への書込み */

#define PIOD_READ_I

3

/* 命令空間からの読取り */

#define PIOD_WRITE_I

4

/* 命令空間への書込み */

data 引数は無視されます。実際に読み書きされたバイト数は、上 記の piod_len に入れられ返されます。

       PT_CONTINUE

トレースされるプロセスは実行を継続します。 addr 引数は、実 行が再開される場所 (プログラムカウンタの新しい値)、または実 行が停止されたところで再開されることを示す (
caddr_t
)1 を 指定します。 data 引数には、トレースされるプロセスが実行を 再開するときに受信するシグナル番号、またはシグナルを送信し ない場合には 0 を指定します。

PT_STEP
トレースされるプロセスは 1 命令ずつステップ実行されます。 addr 引数には (
caddr_t
)1 を渡す必要があります。 data には 実行の再開のために、トレースされたプロセスへ配信されるべき シグナルの数を与えます。または、送られるべきシグナルが無い 場合には 0 を与えます。

PT_KILL
トレースされるプロセスは、あたかも SIGKILL を配信シグナルと して PT_CONTINUE が使用されたかのように、終了します。

PT_ATTACH
この要求は、他の無関係なプロセスの制御を取得し、そのトレー スを開始します。トレースされるプロセスからの協力は必要とし ません。このケースでは、 pid にトレースされるプロセスのプロ セス ID を指定し、他の 2 つの引数は無視されます。この要求で は、ターゲットプロセスがトレースするプロセスと同じ実 UID を 持つこと、それが setuid または setgid された実行可能モ ジュールでないことが要求されます (トレースするプロセスが root として実行されている場合、これらの制約は適用されませ ん)。トレースするプロセスは、新たにトレースされるプロセスを 停止させ、あたかも最初からずっとトレースしていたかのように 制御できます。

PT_DETACH
この要求は PT_CONTINUE と類似していますが、実行を継続する別 の場所を指定できないこと、および要求が成功した後、トレース されていたプロセスはもはやトレースされず、通常どおり実行を 継続することが異なります。

PT_GETREGS
この要求は、トレースされるプロセスのマシンレジスタを、 addr が指す ‘‘
struct reg
’’ (<machine/reg.h> 内に定義されていま す) 内に読み取ります。

PT_SETREGS
この要求は PT_GETREGS の逆です。 addr が指す ‘‘
struct reg
’’ (<machine/reg.h> 内に定義されています) からトレースさ れるプロセスのマシンレジスタをロードします。

PT_GETFPREGS
この要求はトレースされるプロセスの浮動小数点レジスタを addr が指す ‘‘
struct fpreg
’’ (<machine/reg.h> に定義されていま す) に読み取ります。

PT_SETFPREGS
この要求は PT_GETFPREGS の反対です。 addr が指す ‘‘
struct fpreg
’’ (<machine/reg.h> 内に定義されています) からトレース されるプロセスの浮動小数点レジスタをロードします。

PT_GETDBREGS
この要求はトレースされるプロセスのデバッグレジスタを addr が指す ‘‘
struct dbreg
’’ (<machine/reg.h> 内に定義されてい ます) に読み取ります。

PT_SETDBREGS
この要求は PT_GETDBREGS の反対です。 addr の指す ‘‘
struct dbreg
’’ (<machine/reg.h> 内に定義されています) からトレース されるプロセスのデバッグレジスタにロードします。

PT_LWPINFO
この要求は、トレースされるプロセスが停止する原因となった ( 軽量プロセスとしても知られる) カーネルスレッドについての情 報を獲得するために使用されます。 addr 引数は以下のように定 義される struct ptrace_lwpinfo へのポインタを指定します:

struct ptrace_lwpinfo {

lwpid_t

pl_lwpid;

/* LWP 識別子 */

int

pl_event;

/* 受け取ったイベント */

};

data 引数は、呼び出し側に知られている構造体の大きさに設定さ れます。これにより、古いプログラムに影響を与えること無し に、この構造体を大きくすることができます。

さらにマシン固有の要求が存在することがあります。

戻り値

いくつかの要求で ptrace() はエラー以外の場合にも −1 を返します。曖昧さを なくすためには、呼び出しの前に errno を 0 に設定し、後でチェックします。

エラー

ptrace() システムコールは次の場合に処理に失敗します。

       [ESRCH]

指定されたプロセス ID を持つプロセスが存在しませ ん。

[EINVAL]
プロセスが自分自身に対して PT_ATTACH を使おうとし ました。
request 引数が正しい要求の 1 つではありませんでし た。
PT_CONTINUE へのシグナル番号 (data) が 0 でない か、または正しいシグナル番号ではありませんでした。
PT_GETREGS, PT_SETREGS, PT_GETFPREGS, PT_SETFPREGS, PT_GETDBREGS または PT_SETDBREGS が、有効なレジスタセットを設定せずに使用されました (これが真になるのは、通常、システムプロセスについ てのみです)。

[EBUSY]
PT_ATTACH が既にトレース中のプロセスについて使用さ れました。
要求をしているプロセス以外のプロセスによって、ト レースされるプロセスを操作しようとする要求が試みら れました。
要求 (PT_ATTACH 以外の) が停止されていないプロセス を指定しました。

[EPERM]
要求 (PT_ATTACH 以外の) が、まったくトレースされて いないプロセスを操作しようとしました。
前述の PT_ATTACH で説明した条件を満たさないプロセ スについて PT_ATTACH を使おうとしました。

関連項目

execve(2), sigaction(2), wait(2), execv(3), i386_clr_watch(3), i386_set_watch(3)

歴史

ptrace() 関数は Version 7 AT&T UNIX で登場しました。

FreeBSD 10.0 August 11, 2003 FreeBSD 10.0

スポンサーリンク