UNIX 6th code reading - トレース

はじめに

今回はトレースを見ていきます。

トレースとは

トレースとは子プロセスがソフトウェア割り込みを受け付けるたびに、親プロセスが介入する機会が与えられる機構のことです。

ptraceというシステムコールを使って、別のプロセスのデータなどを操作できるようです。デバッグなどに用いるそうです(?)

このあたりが参考になると思います。

stop

プロセスをSTOP状態にします。この状態になると、親プロセスに通知され、親プロセスは子プロセスに対してコマンドを送ることができるようになります。子プロセスはコマンドを受け取った後、その処理を行います。

トレースフラグ(STRC)が立っているとき、issig( )からstop( )が呼ばれます。

  • 4022 : 親プロセスがproc#1(ブートストラッププロセス)でなければ
    • 4023-4027 : 親プロセスを起こし、カレントプロセスはSTOP状態(SSTOP)にする。その後swtchを呼び出してカレントプロセスを切り替える。親プロセスが選択されることを期待している?
    • 4028-4030 : 親プロセスによるptraceでsetrun(4188)された後に、swtchでせんたくされたらここから処理再開。トレースフラグが立っていないかprocxmt( )の結果が真ならreturnして通常処理を続行する。そうでなければループし、再度親を探す
  • 4032 : 親プロセスがproc#1ならばexit( )を呼び出して終了する

ptrace

ptraceシステムコールを実現します。トレースする子プロセスに対して「こういう処理をしろ」と命令します。親プロセスと子プロセスはipc(3933)という構造体を使ってやり取りをします。

  • 4168-4171 : ptraceシステムコールに対する第三引数が0以下ならば、カレントプロセスのトレースフラグを立ててreturn. 第三引数はトレース時に行うコマンド種別を表す。ただし0の場合は子プロセスが親プロセスからトレースされるという意味を表し、他の数字とは区別される
  • 4172-4178 : 全プロセスを探査し、以下の条件に合うものを探す。発見したらfoundへ飛ぶ。見つからなければエラー
    • SSTOP状態
    • pidがptraceシステムコールに対する第一引数に等しい。第一引数はトレースするプロセスのidを表す
    • 親プロセスがカレントプロセス(つまりカレントプロセスの子プロセスである)
  • 4181-4182 : ipcのロックが取得できなければ寝る
  • 4183-4186 : ipcをロックした後ipcにパラメータを詰め込む
  • 4187 : 子プロセスのSWTEDフラグを解除する
  • 4188 : 子プロセスをSRUN状態にする
  • 4189-4190 : ipcのip_reqが0以下になるまで寝る。子プロセスが実行するprocxmt( )内でip_reqが0にセットされる。つまり子プロセスがip_reqを実行するまで寝る
  • 4191 : (子プロセスがprocxmt( )を実行し)処理が戻ってきた後、ptraceシステムコールからの返り値として?r0にipc.ip_dataを格納する
  • 4192-4193 : ipc.ip_reqが0以上ならばエラー。procxmt( )処理でエラーの場合を想定している?(4281)
  • 4194 : ipcのロックを解除する
  • 4195 : 4182で寝ているプロセスを起こす。4190で寝ているプロセスまで起きてしまうので、Lions本で書かれているようにipc.ip_reqなどで制御したほうがいいと思う

procxmt

トレースされる子プロセスが実行する関数。ptrace( )にて親に設定されたipcの内容によって、データを読んだり書いたりなどの処理を行います。

  • 4209-4210 : ロックが正しくかかっていなければreturn. このロックは4183でかけられることを期待する
  • 4212-4213 : ip_reqをリセットしてから4190で寝ているプロセスを起こす。4182で寝ているプロセスも起こしてしまうので、以下同様
  • 4214-4284 : ipc.ip_req次第で様々な処理を行う。つまり、親プロセスに指定された処理を行う


処理の種類はmanualからの引用で説明の代わりとします。ただし1&2と4&5でそれぞれI, Dの処理が逆なので注意してください。

The value of the request argument determines the precise action of the call:
0 This request is the only one used by the child process; it declares that the process is to be traced by its
parent. All the other arguments are ignored. Peculiar results will ensue if the parent does not expect
to trace the child.
1,2 The word in the child process’s address space at addr is returned (in r0). Request 1 indicates the data
space (normally used); 2 indicates the instruction space (when I and D space are separated). addr
must be even. The child must be stopped. The input data is ignored.
3 The word of the system’s per-process data area corresponding to addr is returned. Addr must be even
and less than 512. This space contains the registers and other information about the process; its layout
corresponds to the user structure in the system.
4,5 The given data is written at the word in the process’s address space corresponding to addr, which must
be even. No useful value is returned. Request 4 specifies data space (normally used), 5 specifies instruction
space. Attempts to write in pure procedure result in termination of the child, instead of going
through or causing an error for the parent.
6 The process’s system data is written, as it is read with request 3. Only a few locations can be written
in this way: the general registers, the floating point status and registers, and certain bits of the processor
status word.
7 The data argument is taken as a signal number and the child’s execution continues as if it had incurred
that signal. Normally the signal number will be either 0 to indicate that the signal which caused the
stop should be ignored, or that value fetched out of the process’s image indicating which signal caused
the stop.
8 The traced process terminates.

7の場合は子プロセスに対してソフトウェア割り込みを行います。この場合はreturn 1でstop( )に戻り(4028)、子プロセスは処理を続行します。

8の場合はexit( )を呼び出して強制的に終了します。

それ以外の場合はreturn 0でstop( )に戻り、子プロセスはSTOP状態のまま待ちます(?)

トレースのフロー

トレース周りの処理の流れがわかりにくかったので絵にしてみました。

理解に自信がないので、間違っていたら申し訳ないです。

追記:Lions本読書会#7の参加後、少し絵を更新しました

終わりに

ようやく13章が終わりました。細かい部分の理解が追いついていないので、Lions本勉強会などを活用して理解を深めていきたいです。

次回は14章のスワッピング処理を見ていきます。