Linuxでプログラムが実行するシステムコールを表示する!(strace)

プログラムが実行するシステムコールを確認する場合は、「strace」コマンドを使用します。

簡単なプログラムを確認してみる!(echo)

画面に文字を出力するみのechoコマンドでstraceを実行してみます。

$ strace echo aaa
execve("/usr/bin/echo", ["echo", "aaa"], 0x7ffd6a2bd248 /* 54 vars */) = 0
brk(NULL)                               = 0x5579614ee000
arch_prctl(0x3001 /* ARCH_??? */, 0x7ffecf0642d0) = -1 EINVAL (Invalid argument)
mmap(NULL, 8192, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7fcbbc43f000
access("/etc/ld.so.preload", R_OK)      = -1 ENOENT (No such file or directory)
openat(AT_FDCWD, "/etc/ld.so.cache", O_RDONLY|O_CLOEXEC) = 3
newfstatat(3, "", {st_mode=S_IFREG|0644, st_size=87699, ...}, AT_EMPTY_PATH) = 0
mmap(NULL, 87699, PROT_READ, MAP_PRIVATE, 3, 0) = 0x7fcbbc429000
close(3)                                = 0
openat(AT_FDCWD, "/lib/x86_64-linux-gnu/libc.so.6", O_RDONLY|O_CLOEXEC) = 3
read(3, "\177ELF\2\1\1\3\0\0\0\0\0\0\0\0\3\0>\0\1\0\0\0P\237\2\0\0\0\0\0"..., 832) = 832
pread64(3, "\6\0\0\0\4\0\0\0@\0\0\0\0\0\0\0@\0\0\0\0\0\0\0@\0\0\0\0\0\0\0"..., 784, 64) = 784
pread64(3, "\4\0\0\0 \0\0\0\5\0\0\0GNU\0\2\0\0\300\4\0\0\0\3\0\0\0\0\0\0\0"..., 48, 848) = 48
pread64(3, "\4\0\0\0\24\0\0\0\3\0\0\0GNU\0i8\235HZ\227\223\333\350s\360\352,\223\340."..., 68, 896) = 68
newfstatat(3, "", {st_mode=S_IFREG|0644, st_size=2216304, ...}, AT_EMPTY_PATH) = 0
pread64(3, "\6\0\0\0\4\0\0\0@\0\0\0\0\0\0\0@\0\0\0\0\0\0\0@\0\0\0\0\0\0\0"..., 784, 64) = 784
mmap(NULL, 2260560, PROT_READ, MAP_PRIVATE|MAP_DENYWRITE, 3, 0) = 0x7fcbbc201000
mmap(0x7fcbbc229000, 1658880, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x28000) = 0x7fcbbc229000
mmap(0x7fcbbc3be000, 360448, PROT_READ, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x1bd000) = 0x7fcbbc3be000
mmap(0x7fcbbc416000, 24576, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x214000) = 0x7fcbbc416000
mmap(0x7fcbbc41c000, 52816, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS, -1, 0) = 0x7fcbbc41c000
close(3)                                = 0
mmap(NULL, 12288, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7fcbbc1fe000
arch_prctl(ARCH_SET_FS, 0x7fcbbc1fe740) = 0
set_tid_address(0x7fcbbc1fea10)         = 11923
set_robust_list(0x7fcbbc1fea20, 24)     = 0
rseq(0x7fcbbc1ff0e0, 0x20, 0, 0x53053053) = 0
mprotect(0x7fcbbc416000, 16384, PROT_READ) = 0
mprotect(0x55795f560000, 4096, PROT_READ) = 0
mprotect(0x7fcbbc479000, 8192, PROT_READ) = 0
prlimit64(0, RLIMIT_STACK, NULL, {rlim_cur=8192*1024, rlim_max=RLIM64_INFINITY}) = 0
munmap(0x7fcbbc429000, 87699)           = 0
getrandom("\x0c\xde\xfc\xfa\x80\xc5\xf7\xcc", 8, GRND_NONBLOCK) = 8
brk(NULL)                               = 0x5579614ee000
brk(0x55796150f000)                     = 0x55796150f000
openat(AT_FDCWD, "/usr/lib/locale/locale-archive", O_RDONLY|O_CLOEXEC) = 3
newfstatat(3, "", {st_mode=S_IFREG|0644, st_size=6784496, ...}, AT_EMPTY_PATH) = 0
mmap(NULL, 6784496, PROT_READ, MAP_PRIVATE, 3, 0) = 0x7fcbbbb85000
close(3)                                = 0
newfstatat(1, "", {st_mode=S_IFCHR|0620, st_rdev=makedev(0x88, 0), ...}, AT_EMPTY_PATH) = 0
write(1, "aaa\n", 4aaa
)                    = 4
close(1)                                = 0
close(2)                                = 0
exit_group(0)                           = ?
+++ exited with 0 +++

別なコマンドを実行してみる!(locale)

少し動作が多くなるlocaleコマンドで実行してみます。

$ strace locale
execve("/usr/bin/locale", ["locale"], 0x7ffd794db690 /* 54 vars */) = 0
brk(NULL)                               = 0x55c85ebe5000
arch_prctl(0x3001 /* ARCH_??? */, 0x7fff6c005920) = -1 EINVAL (Invalid argument)
mmap(NULL, 8192, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7f82f8f69000
access("/etc/ld.so.preload", R_OK)      = -1 ENOENT (No such file or directory)
openat(AT_FDCWD, "/etc/ld.so.cache", O_RDONLY|O_CLOEXEC) = 3
newfstatat(3, "", {st_mode=S_IFREG|0644, st_size=87699, ...}, AT_EMPTY_PATH) = 0
mmap(NULL, 87699, PROT_READ, MAP_PRIVATE, 3, 0) = 0x7f82f8f53000
close(3)                                = 0
openat(AT_FDCWD, "/lib/x86_64-linux-gnu/libc.so.6", O_RDONLY|O_CLOEXEC) = 3
read(3, "\177ELF\2\1\1\3\0\0\0\0\0\0\0\0\3\0>\0\1\0\0\0P\237\2\0\0\0\0\0"..., 832) = 832
pread64(3, "\6\0\0\0\4\0\0\0@\0\0\0\0\0\0\0@\0\0\0\0\0\0\0@\0\0\0\0\0\0\0"..., 784, 64) = 784
pread64(3, "\4\0\0\0 \0\0\0\5\0\0\0GNU\0\2\0\0\300\4\0\0\0\3\0\0\0\0\0\0\0"..., 48, 848) = 48
pread64(3, "\4\0\0\0\24\0\0\0\3\0\0\0GNU\0i8\235HZ\227\223\333\350s\360\352,\223\340."..., 68, 896) = 68
newfstatat(3, "", {st_mode=S_IFREG|0644, st_size=2216304, ...}, AT_EMPTY_PATH) = 0
pread64(3, "\6\0\0\0\4\0\0\0@\0\0\0\0\0\0\0@\0\0\0\0\0\0\0@\0\0\0\0\0\0\0"..., 784, 64) = 784
mmap(NULL, 2260560, PROT_READ, MAP_PRIVATE|MAP_DENYWRITE, 3, 0) = 0x7f82f8d2b000
mmap(0x7f82f8d53000, 1658880, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x28000) = 0x7f82f8d53000
mmap(0x7f82f8ee8000, 360448, PROT_READ, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x1bd000) = 0x7f82f8ee8000
mmap(0x7f82f8f40000, 24576, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x214000) = 0x7f82f8f40000
mmap(0x7f82f8f46000, 52816, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS, -1, 0) = 0x7f82f8f46000
close(3)                                = 0
mmap(NULL, 12288, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7f82f8d28000
arch_prctl(ARCH_SET_FS, 0x7f82f8d28740) = 0
set_tid_address(0x7f82f8d28a10)         = 11945
set_robust_list(0x7f82f8d28a20, 24)     = 0
rseq(0x7f82f8d290e0, 0x20, 0, 0x53053053) = 0
mprotect(0x7f82f8f40000, 16384, PROT_READ) = 0
mprotect(0x55c85e6f4000, 4096, PROT_READ) = 0
mprotect(0x7f82f8fa3000, 8192, PROT_READ) = 0
prlimit64(0, RLIMIT_STACK, NULL, {rlim_cur=8192*1024, rlim_max=RLIM64_INFINITY}) = 0
munmap(0x7f82f8f53000, 87699)           = 0
getrandom("\xd5\x5d\xb9\xde\xc3\xb3\xcc\x2b", 8, GRND_NONBLOCK) = 8
brk(NULL)                               = 0x55c85ebe5000
brk(0x55c85ec06000)                     = 0x55c85ec06000
openat(AT_FDCWD, "/usr/lib/locale/locale-archive", O_RDONLY|O_CLOEXEC) = 3
newfstatat(3, "", {st_mode=S_IFREG|0644, st_size=6784496, ...}, AT_EMPTY_PATH) = 0
mmap(NULL, 6784496, PROT_READ, MAP_PRIVATE, 3, 0) = 0x7f82f86af000
close(3)                                = 0
newfstatat(1, "", {st_mode=S_IFCHR|0620, st_rdev=makedev(0x88, 0), ...}, AT_EMPTY_PATH) = 0
write(1, "LANG=en_US.UTF-8\n", 17LANG=en_US.UTF-8
)      = 17
write(1, "LANGUAGE=\n", 10LANGUAGE=
)             = 10
write(1, "LC_CTYPE=\"en_US.UTF-8\"\n", 23LC_CTYPE="en_US.UTF-8"
) = 23
write(1, "LC_NUMERIC=en_US.UTF-8\n", 23LC_NUMERIC=en_US.UTF-8
) = 23
write(1, "LC_TIME=en_US.UTF-8\n", 20LC_TIME=en_US.UTF-8
)   = 20
write(1, "LC_COLLATE=\"en_US.UTF-8\"\n", 25LC_COLLATE="en_US.UTF-8"
) = 25
write(1, "LC_MONETARY=en_US.UTF-8\n", 24LC_MONETARY=en_US.UTF-8
) = 24
write(1, "LC_MESSAGES=\"en_US.UTF-8\"\n", 26LC_MESSAGES="en_US.UTF-8"
) = 26
write(1, "LC_PAPER=en_US.UTF-8\n", 21LC_PAPER=en_US.UTF-8
)  = 21
write(1, "LC_NAME=en_US.UTF-8\n", 20LC_NAME=en_US.UTF-8
)   = 20
write(1, "LC_ADDRESS=en_US.UTF-8\n", 23LC_ADDRESS=en_US.UTF-8
) = 23
write(1, "LC_TELEPHONE=en_US.UTF-8\n", 25LC_TELEPHONE=en_US.UTF-8
) = 25
) = 27
write(1, "LC_IDENTIFICATION=en_US.UTF-8\n", 30LC_IDENTIFICATION=en_US.UTF-8
) = 30
write(1, "LC_ALL=\n", 8LC_ALL=
)                = 8
exit_group(0)                           = ?
+++ exited with 0 +++

Linuxのプログラムの起動と停止に関連する共通の部分と、独自の部分が見えてきます。

出力結果をファイルに保存する!

出力結果は多量になることが多いので、ファイルに出力したくなると思います。「-o」オプションで出力ファイルを指定できます。

$ strace -o strace.log locale
LANG=en_US.UTF-8
LANGUAGE=
LC_CTYPE="en_US.UTF-8"
LC_NUMERIC=en_US.UTF-8
LC_TIME=en_US.UTF-8
LC_COLLATE="en_US.UTF-8"
LC_MONETARY=en_US.UTF-8
LC_MESSAGES="en_US.UTF-8"
LC_PAPER=en_US.UTF-8
LC_NAME=en_US.UTF-8
LC_ADDRESS=en_US.UTF-8
LC_TELEPHONE=en_US.UTF-8
LC_MEASUREMENT=en_US.UTF-8
LC_IDENTIFICATION=en_US.UTF-8
LC_ALL=

おわりに

straceコマンドを実行すると、使用しているシステムコールを確認することができます。いろいろ実行してみるとLinuxのプログラムの動きが見えてくると思います。

関連記事

関連書籍(Amazon)

N/A