How to Debug Programs by Intercepting Library Calls Using ltrace in Linux

When a custom-compiled application or a third-party binary repeatedly crashes on a Linux server, identifying the root cause can be incredibly difficult, especially if you do not have access to the original source code. While the strace command is excellent for tracking how a program interacts with the Linux kernel, many crashes occur in “user space” when the program attempts to call a function from a shared library (like libc or libcrypto). To precisely intercept and record every single dynamic library call a process makes before it dies, you must use the ltrace command.

How the ltrace Command Works

The ltrace (Library Trace) utility acts as a microscopic wiretap attached directly between your target executable and the system’s dynamic linker. When you wrap a command in ltrace, the utility intercepts every single time the program asks a shared library to perform a task (e.g., asking the C library to allocate memory using malloc() or asking it to compare two strings using strcmp()). It records the function name, the exact arguments passed into it, and the final value returned by the library.

Because it is a specialized debugging tool, it is usually not installed by default. You can install it on Debian/Ubuntu systems using sudo apt install ltrace.

How to Trace a Crashing Program

To trace an application, simply place ltrace in front of the command you want to execute.

ltrace ./buggy_application.bin

The terminal will output a massive, rapidly scrolling list of function calls. Each line represents a single interaction.

strlen("Admin") = 5
malloc(1024) = 0x5560b4c2a010
strcmp("Admin", "Guest") = -6
strcpy(0x5560b4c2a010, "Access Denied") = 0x5560b4c2a010

By reading the output chronologically, you can see the exact logical path the program took. If the program crashes, you simply look at the very last line printed by ltrace. If the final line shows the program attempting to call fopen("/etc/custom_config.conf") = NULL right before the crash, you instantly know the program died because a specific configuration file is missing from the hard drive.

How to Filter the Trace Output

A complex application might make tens of thousands of library calls per second, completely burying the crucial error data under a mountain of irrelevant noise. You can use the -e (expression) flag to filter the output, forcing ltrace to only intercept specific functions.

For example, if you suspect a program has a memory leak, you do not care about string comparisons; you only want to see memory allocation calls.

ltrace -e malloc,free ./memory_hog.bin

This command instructs the wiretap to ignore everything else and only print a line to the screen when the program explicitly calls the malloc or free functions, drastically reducing the noise and allowing you to easily pinpoint exactly where the memory is being requested but never released.

Get the best tech tips delivered straight to your inbox.

Join thousands of readers mastering Apple, Google, Microsoft, and Linux.