ITコンサルの日常

ITコンサル会社に勤務する普通のITエンジニアの日常です。

straceでシステムコールをトレースする

BINARY HACKS p311

straceってのは、

ptrace(PTRACE_SYSCALL, ...)でシステムコールの入り口と出口をフックして、システムコールの引数と戻り値を出力することです。

とのことです。AOPっぽい?

普通にHello, Worldを書いて試してみる。

taka@ubuntu:~$ more hello.c
#include 

int main()
{
        printf("Hello, World\n");
}
taka@ubuntu:~$ cc -o hello hello.c
taka@ubuntu:~$ ./hello
Hello, World
taka@ubuntu:~$ strace ./hello
execve("./hello", ["./hello"], [/* 17 vars */]) = 0
uname({sys="Linux", node="ubuntu", ...}) = 0
brk(0)                                  = 0x804a000
old_mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0xb7fea000
access("/etc/ld.so.nohwcap", F_OK)      = -1 ENOENT (No such file or directory)
old_mmap(NULL, 8192, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0xb7fe8000
access("/etc/ld.so.preload", R_OK)      = -1 ENOENT (No such file or directory)
open("/etc/ld.so.cache", O_RDONLY)      = 3
fstat64(3, {st_mode=S_IFREG|0644, st_size=17520, ...}) = 0
old_mmap(NULL, 17520, PROT_READ, MAP_PRIVATE, 3, 0) = 0xb7fe3000
close(3)                                = 0
access("/etc/ld.so.nohwcap", F_OK)      = -1 ENOENT (No such file or directory)
open("/lib/tls/i686/cmov/libc.so.6", O_RDONLY) = 3
read(3, "\177ELF\1\1\1\0\0\0\0\0\0\0\0\0\3\0\3\0\1\0\0\0\220O\1"..., 512) = 512
fstat64(3, {st_mode=S_IFREG|0755, st_size=1232784, ...}) = 0
old_mmap(NULL, 1238972, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_DENYWRITE, 3, 0) = 0xb7eb4000
old_mmap(0xb7fd9000, 28672, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x125000) = 0xb7fd9000
old_mmap(0xb7fe0000, 10172, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS, -1, 0) = 0xb7fe0000
close(3)                                = 0
old_mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0xb7eb3000
set_thread_area({entry_number:-1 -> 6, base_addr:0xb7eb38e0, limit:1048575, seg_32bit:1, contents:0, read_exec_only:0, limit_in_pages:1, seg_not_present:0, useable:1}) = 0
munmap(0xb7fe3000, 17520)               = 0
fstat64(1, {st_mode=S_IFCHR|0620, st_rdev=makedev(136, 0), ...}) = 0
mmap2(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0xb7fe7000
write(1, "Hello, World\n", 13Hello, World
)          = 13
munmap(0xb7fe7000, 4096)                = 0
exit_group(13)                          = ?

8行目くらいにopenシステムコールがありますが、戻り値がいきなり3になっています。
これが昨日のナゾを解くヒントになったわけですが、本書中にもあるように、

「設定ファイルを作ったのになぜか反映されない。果たして読み込まれているのだろうか」というときはstraceを使って、その設定ファイルがプログラムによって開かれているか確認すると便利です。

とのことで、もちろん、

strace ruby hello.rb

みたいなことも出来るので、いろんな場面で役立ちそうです。