同僚に教えてもらった gdb で実行中のプロセスにアタッチして、writeシステムコール発行直前でレジスタのファイルディスクリプタを書換えるというのを試してみた。
- write_loop.c
#include <unistd.h> int main(void) { while(1) { write(1, "foo\n", 4); } }
- コンパイルする
$ gcc -o write_loop write_loop.c
- 実行する
$ ./write_loop > foo.log
- PID を調べて、
$ ps auxw|grep [w]rite_loop yazekats 5873 97.6 0.0 3968 284 pts/0 R+ 22:01 1:18 ./write_loop
- ファイルディスクリプタを確認する。
$ ls -l /proc/5873/fd total 0 lrwx------ 1 yazekats yazekats 64 Dec 19 22:10 0 -> /dev/pts/0 l-wx------ 1 yazekats yazekats 64 Dec 19 22:10 1 -> /home/yazekats/Documents/work/foo.log lrwx------ 1 yazekats yazekats 64 Dec 19 22:03 2 -> /dev/pts/0
- gdb でプロセスにアタッチする
$ gdb -p 5873 (gdb) b write Breakpoint 1 at 0x3ba66db780 (gdb) n Single stepping until exit from function write, which has no line number information. 0x00000000004004dc in main () (gdb) n Single stepping until exit from function main, which has no line number information. Breakpoint 1, 0x0000003ba66db780 in write () from /lib64/libc.so.6 (gdb) info reg rax 0x4 4 rbx 0x0 0 rcx 0xffffffffffffffff -1 rdx 0x4 4 rsi 0x4005d8 4195800 rdi 0x1 1 ★FDは1の標準出力 rbp 0x7fff77c9b5a0 0x7fff77c9b5a0 rsp 0x7fff77c9b598 0x7fff77c9b598 r8 0x3ba698f300 256198112000 r9 0x3ba620e9f0 256190245360 r10 0x7fff77c9b320 140735203095328 r11 0x246 582 r12 0x4003e0 4195296 r13 0x7fff77c9b680 140735203096192 r14 0x0 0 r15 0x0 0 rip 0x3ba66db790 0x3ba66db790 <__write_nocancel+7> eflags 0x246 [ PF ZF IF ] cs 0x33 51 ss 0x2b 43 ds 0x0 0 es 0x0 0 fs 0x0 0 gs 0x0 0 (gdb) set $rdi=2 (gdb) info reg rax 0x4 4 rbx 0x0 0 rcx 0xffffffffffffffff -1 rdx 0x4 4 rsi 0x4005d8 4195800 rdi 0x2 2 ★FDが2の標準エラーに変わっている rbp 0x7fff77c9b5a0 0x7fff77c9b5a0 rsp 0x7fff77c9b598 0x7fff77c9b598 r8 0x3ba698f300 256198112000 r9 0x3ba620e9f0 256190245360 r10 0x7fff77c9b320 140735203095328 r11 0x246 582 r12 0x4003e0 4195296 r13 0x7fff77c9b680 140735203096192 r14 0x0 0 r15 0x0 0 rip 0x3ba66db790 0x3ba66db790 <__write_nocancel+7> eflags 0x246 [ PF ZF IF ] cs 0x33 51 ss 0x2b 43 ds 0x0 0 es 0x0 0 fs 0x0 0 gs 0x0 0 (gdb) n
お、標準エラーに出力された!
$ ./write_loop > foo.log
foo ← これが出力される