揮発性のメモ2

知識をメモ書きしておく

走行中のプロセスの標準出力を横取りする方法

横取りというか覗き見る。つづき


SH4でも使いたかったけど、当然コンパイルが通らないのでなんとかする。
straceのソースを読んでみても、ぐちゃぐちゃしててよくわからなかった。レジスタとかよく知らないので、とりあえずstraceをstraceしてみる。

$ strace -e trace=ptrace strace -e trace=write echo hoge

i686の場合

ptrace(PTRACE_PEEKUSER, 20205, 4*ORIG_EAX, [0x4]) = 0
ptrace(PTRACE_PEEKUSER, 20205, 4*EAX, [0xffffffda]) = 0
ptrace(PTRACE_PEEKUSER, 20205, 4*EBX, [0x1]) = 0
ptrace(PTRACE_PEEKUSER, 20205, 4*ECX, [0xb7f21000]) = 0
ptrace(PTRACE_PEEKUSER, 20205, 4*EDX, [0x5]) = 0
ptrace(PTRACE_PEEKDATA, 20205, 0xb7f21000, [0x65676f68]) = 0
ptrace(PTRACE_PEEKDATA, 20205, 0xb7f21004, [0xa]) = 0
write(1, "hoge\n", 5ptrace(PTRACE_SYSCALL, 20205, 0x1, SIG_0) = 0
hoge
ptrace(PTRACE_PEEKUSER, 1301, 4*REG_REG3, [0x4]) = 0
ptrace(PTRACE_PEEKUSER, 1301, 4*REG_REG0, [0x5]) = 0
)                   = 5

sh4の場合

ptrace(PTRACE_PEEKUSER, 1301, 4*REG_REG3, [0x4]) = 0
ptrace(PTRACE_PEEKUSER, 1301, 4*REG_REG0, [0]) = 0
ptrace(PTRACE_PEEKUSER, 1301, 4*REG_REG4, [0x1]) = 0
ptrace(PTRACE_PEEKUSER, 1301, 4*REG_REG5, [0x2956c000]) = 0
ptrace(PTRACE_PEEKUSER, 1301, 4*REG_REG6, [0x5]) = 0
ptrace(PTRACE_PEEKDATA, 1301, 0x2956c000, [0x65676f68]) = 0
ptrace(PTRACE_PEEKDATA, 1301, 0x2956c004, [0xa]) = 0
write(1, "hoge\n", 5ptrace(PTRACE_SYSCALL, 1301, 0x1, SIG_0) = 0
hoge
ptrace(PTRACE_PEEKUSER, 21209, 4*ORIG_EAX, [0x4]) = 0
ptrace(PTRACE_PEEKUSER, 21209, 4*EAX, [0x5]) = 0
)                   = 5

レジスタの構成

レジスタ i686 sh
システムコール番号 orig_eax REG_REG3
出るときは戻り値。入るときはわかんない eax REG_REG0
システムコールの第1引数 ebx REG_REG4
システムコールの第2引数 ecx REG_REG5
システムコールの第3引数 edx REG_REG6
システムコールの第4引数 esi REG_REG7
システムコールの第5引数 edi REG_REG8

たぶんこんな感じで対応。
REG_REG3なんていう定義はどのヘッダにも書いてないので、自分で適当につける。SH4のasm/ptrace.hには

#define REG_REG0         0
#define REG_REG15       15

と書いてあったので、これから推測して適当に即値をつける。


スレッドを使ったプログラムだと、親スレッドの出力しか覗けない。
straceコマンドだと、-fとか-Fオプションを付ければスレッドのシステムコールも追うことが出来る。(つまりプロセス扱い)
どうやってんのかとstraceのソースを追ってみたら、/proc/(pid)/taskを見てた。どうやらここで得たプロセスID全部に対して 何かやってるっぽい。
あと、sarge用のstraceにはバグがあって、スレッドを使ったプログラムを追うと、Ctrl+Cでデタッチしきれなくなって元のプロセスごと殺すしかなくなる。迷惑すぎる。