LinuxCommandLibrary

ltrace

Trace library calls of a program

TLDR

Print (trace) library calls of a program binary

$ ltrace ./[program]
copy

Count library calls. Print a handy summary at the bottom
$ ltrace -c [path/to/program]
copy

Trace calls to malloc and free, omit those done by libc
$ ltrace -e malloc+free-@libc.so* [path/to/program]
copy

Write to file instead of terminal
$ ltrace [[-o|--output]] [file] [path/to/program]
copy

SYNOPSIS

ltrace [options] [command [arguments]]
ltrace [options] -p pid

PARAMETERS

-c
    Count library calls and print a summary report upon exit, including the time spent in each call.

-e
    A qualifying expression that specifies which library calls to trace or exclude. can use + (trace), - (do not trace), or specific function patterns (e.g., +memcpy, -strlen).

-f
    Trace child processes as they are created by fork(), vfork(), or clone().

-i
    Print the instruction pointer (program counter) at the time of the library call.

-l
    Trace calls only from a specific library. can be a library name (e.g., libc.so.6 or libpthread).

-o
    Redirect the trace output to the specified instead of standard error.

-p
    Attach to an already running process with the given process ID ().

-r
    Print a relative timestamp (in microseconds) showing the time elapsed since the beginning of the trace.

-s
    Specify the maximum string (in bytes) to print. Longer strings will be truncated with '...'.

-S
    Display system calls in addition to library calls, similar to strace's output.

-t
    Print an absolute timestamp for each line of output, showing the current time of day.

-T
    Show the time spent in each library call, from its entry to its return. This time is printed on the call's return line.

-V
    Display the version number of ltrace and exit.

-x
    A qualifying expression for system calls to trace or exclude. Similar to -e, but specifically for syscalls (e.g., +open, -read).

DESCRIPTION

ltrace is a powerful diagnostic and debugging utility for Linux that intercepts and records dynamic library calls made by a user-space process. It provides insights into a program's runtime behavior by displaying the library function names, their arguments, and return values.

While similar to strace, which traces system calls, ltrace focuses on the higher-level library functions (e.g., libc, libpthread, etc.). This makes it invaluable for understanding how a program interacts with shared libraries, debugging issues related to incorrect library usage, reverse engineering binaries, or analyzing unexpected program behavior without access to source code. It can also trace signals delivered to a process.

CAVEATS

Using ltrace can introduce significant performance overhead to the traced process, potentially slowing it down considerably. It typically requires appropriate permissions (e.g., root privileges or CAP_SYS_PTRACE capability) to attach to or launch processes. Some highly optimized or obfuscated binaries might behave unexpectedly or resist tracing with ltrace. It is primarily effective for dynamically linked executables; tracing statically linked binaries is more complex or not fully supported.

OUTPUT FORMAT

The typical output of ltrace displays the name of the library function called, followed by its arguments enclosed in parentheses. Upon the function's return, an equals sign (=) is printed, followed by the function's return value. For example: read(0, "hello\n", 6) = 6. String arguments are often displayed in a human-readable format, and pointers or complex data structures are summarized.

USAGE SCENARIOS

ltrace is widely used for diagnosing issues like segmentation faults (e.g., by observing incorrect arguments to library functions), identifying missing or incorrect library dependencies, understanding the behavior of closed-source or third-party applications, reverse engineering unknown binaries to analyze their functionality (e.g., network operations, file access, cryptographic calls), and analyzing software for security vulnerabilities by observing API calls.

HISTORY

ltrace was originally developed by Juan Cespedes in the late 1990s as a complementary tool to strace, aiming to provide a higher-level view of program execution by focusing on library calls rather than raw system calls. It quickly became a standard utility on Linux distributions, filling a crucial gap in debugging and analysis toolkits. The project has undergone continuous development and maintenance, evolving to support new Linux kernel features, architectures, and addressing various tracing complexities.

SEE ALSO

strace(1), ldd(1), gdb(1), readelf(1)

Copied to clipboard