ltrace コマンド

プログラムのライブラリ呼び出しをトレースします。

概要

ltrace は、プログラム実行中に行われる動的ライブラリ呼び出しを表示するデバッグユーティリティです。システムコールや受信したシグナルも表示できます。このツールは、プログラムがライブラリとどのように相互作用するかを理解したり、問題を診断したり、アプリケーションのリバースエンジニアリングを行ったりする際に役立ちます。

オプション

-c

時間、呼び出し回数をカウントし、最後に要約レポートを表示します。

$ ltrace -c ls
% time     seconds  usecs/call     calls      function
------ ----------- ----------- --------- --------------------
 28.57    0.000040          8         5 strlen
 21.43    0.000030         15         2 readdir64
 14.29    0.000020         10         2 closedir
 14.29    0.000020         10         2 opendir
  7.14    0.000010         10         1 __errno_location
  7.14    0.000010         10         1 fclose
  7.14    0.000010         10         1 fopen
------ ----------- ----------- --------- --------------------
100.00    0.000140                    14 total

-f

現在トレース中のプロセスによって作成される子プロセスをトレースします。

$ ltrace -f ./parent_program
[pid 12345] malloc(32)                                      = 0x55d45e9a12a0
[pid 12345] fork()                                          = 12346
[pid 12346] malloc(64)                                      = 0x55d45e9a1340

-e PATTERN

トレースするライブラリ呼び出しやトレースしないライブラリ呼び出しを指定します。

$ ltrace -e malloc+free ls
ls->malloc(24)                                             = 0x55d45e9a12a0
ls->malloc(13)                                             = 0x55d45e9a1340
ls->free(0x55d45e9a12a0)                                   = <void>
ls->free(0x55d45e9a1340)                                   = <void>

-p PID

指定されたPIDのプロセスにアタッチしてトレースを開始します。

$ ltrace -p 1234
[pid 1234] read(5, "Hello World", 1024)                    = 11
[pid 1234] write(1, "Hello World", 11)                     = 11

-S

ライブラリ呼び出しに加えてシステムコールも表示します。

$ ltrace -S ls
SYS_brk(NULL)                                              = 0x55d45e9a1000
SYS_access("/etc/ld.so.preload", R_OK)                     = -2
malloc(256)                                                = 0x55d45e9a12a0
SYS_open("/etc/ld.so.cache", O_RDONLY)                     = 3

-o FILENAME

トレース出力を標準エラー出力ではなく、指定したファイルに書き込みます。

$ ltrace -o trace.log ls
$ cat trace.log
malloc(256)                                                = 0x55d45e9a12a0
free(0x55d45e9a12a0)                                       = <void>

使用例

基本的な使い方

$ ltrace ls
__libc_start_main(0x401670, 1, 0x7ffd74a3c648, 0x406750 <unfinished ...>
strrchr("ls", '/')                                         = NULL
setlocale(LC_ALL, "")                                      = "en_US.UTF-8"
bindtextdomain("coreutils", "/usr/share/locale")           = "/usr/share/locale"
textdomain("coreutils")                                    = "coreutils"
__cxa_atexit(0x402860, 0, 0, 0x736c6974)                   = 0
isatty(1)                                                  = 1
getenv("QUOTING_STYLE")                                    = NULL
getenv("COLUMNS")                                          = NULL
ioctl(1, 21523, 0x7ffd74a3c4e0)                            = 0
...
+++ exited (status 0) +++

特定の関数をトレースする

$ ltrace -e malloc+free+open ./program
program->malloc(1024)                                      = 0x55d45e9a12a0
program->open("/etc/passwd", 0, 0)                         = 3
program->free(0x55d45e9a12a0)                              = <void>

時間情報付きでトレースする

$ ltrace -tt ls
15:30:45.789012 __libc_start_main(0x401670, 1, 0x7ffd74a3c648, 0x406750 <unfinished ...>
15:30:45.789234 strrchr("ls", '/')                         = NULL
15:30:45.789456 setlocale(LC_ALL, "")                      = "en_US.UTF-8"
...
15:30:45.795678 +++ exited (status 0) +++

ヒント

ノイズをフィルタリングする

-e オプションを使用して、関心のある特定の関数呼び出しに焦点を当て、出力の混雑を減らします:

$ ltrace -e malloc+free+open ./program

他のツールと組み合わせる

ltraceの出力をgrepにパイプして、特定の関数呼び出しを見つけます:

$ ltrace ./program 2>&1 | grep "open"

子プロセスをトレースする

子プロセスを生成する複雑なアプリケーションをデバッグする場合は、-f を使用して子プロセスも追跡します:

$ ltrace -f ./server

後で分析するために出力を保存する

長時間実行されるプログラムの場合、-o でトレースをファイルに保存します:

$ ltrace -o debug.log ./program

よくある質問

Q1. ltraceとstraceの違いは何ですか?

A. ltrace はライブラリ呼び出し(共有ライブラリからの関数)をトレースし、strace はシステムコール(カーネルとの相互作用)をトレースします。ltrace -S を使用すると両方を見ることができます。

Q2. なぜltraceはすべての関数呼び出しを表示しないのですか?

A. ltrace は外部ライブラリへの呼び出しのみを表示し、プログラム内部の関数呼び出しは表示しません。それにはプロファイラやデバッガが必要です。

Q3. ltraceはトレース対象のプログラムを遅くすることがありますか?

A. はい、トレースには大きなオーバーヘッドがあります。特に -f(フォークを追跡)を有効にすると、プログラムの実行速度は遅くなります。

Q4. すでに実行中のプログラムをトレースするにはどうすればよいですか?

A. ltrace -p PID を使用して、すでに実行中のプロセスにアタッチします。

Q5. 静的にリンクされたバイナリでltraceを使用できますか?

A. いいえ、ltrace は主に動的にリンクされた実行ファイルで動作します。共有ライブラリへの呼び出しを傍受するためです。

参考文献

https://man7.org/linux/man-pages/man1/ltrace.1.html

改訂履歴