ltraceTrace the library calls a program makes
ltrace shows the calls a program makes into shared libraries such as libc: getenv, fopen, malloc, strcmp and friends, with arguments and return values. It answers questions strace can't, like which environment variable a binary looks for or which string it compares your input against.
ltrace [-f] [-c] [-S] [-tt] [-e FILTER] [-s N] [-o FILE] { COMMAND [ARG]... | -p PID }You want to know what settings a program looks up at startup without reading its source code.
ltraceThe library-call tracer. Like strace, it controls the program through ptrace.
ltrace reads the program's ELF dynamic symbol table (.dynsym and .dynstr) to learn which library functions it imports. It starts the program under ptrace and plants breakpoint instructions (int3) on the PLT stubs, the small trampolines every call into a shared library goes through. When a breakpoint fires, the kernel stops the program and ltrace decodes the arguments using prototypes from /usr/share/ltrace/*.conf (it knows getenv takes a string, fopen two strings). It then sets a breakpoint on the return address to catch the return value. Statically linked binaries, including most Go programs, have no dynamic symbol table, so there is nothing to trace. Each traced call costs several context switches, so ltrace is slower than strace. -S adds system calls to the same output.
-e FILTEROnly these functions: getenv+fopen, or 'malloc*' patterns, or -e '@libssl.so*'-cCount calls and time per function, printed as a table at exit-SAlso show system calls (prefixed SYS_), mixed with library calls-fFollow child processes created by fork-p PIDAttach to a running process (needs root on Ubuntu)-tt / -TTimestamp each call / show time spent inside each call-s NMaximum string length to print (default 32)-n NIndent nested calls by N spaces, to see who calls whom-o FILEWrite the trace to FILE instead of stderr-x PATTERNAlso trace internal (non-PLT) functions matching the patternltrace ./myapp on a Go, Rust-musl or other static binary and assuming it does nothingStatic binaries have no PLT or dynamic symbol table, so ltrace has nothing to hook; the program's work is invisible to it.
file ./myapp to check, then strace -f for syscalls or perf record for CPURunning ltrace without -e on a real serviceYou get hundreds of thousands of strlen, memcpy and malloc calls and the program slows to a crawl.
ltrace -e getenv+fopen+connect ... or ltrace -c for a summaryReading ltrace -c times as the real cost of each functionEvery traced call pays for breakpoints and context switches; the overhead (tens of µs) dwarfs a strlen that takes nanoseconds.
Use -c for call counts; use perf to measure real CPU timeTry these on a Linux machine of your own. Each task has a hint and a solution.
Find which environment variables the date command reads.
Count the library calls made by 'ls -l ~/app' and find the most frequent one.
Show both library calls and system calls for 'cat ~/app/README.md' (or any file in ~/app), limited to fopen/open-style calls.
ltraceTrace the library calls a program makes
ltrace shows the calls a program makes into shared libraries such as libc: getenv, fopen, malloc, strcmp and friends, with arguments and return values. It answers questions strace can't, like which environment variable a binary looks for or which string it compares your input against.
ltrace [-f] [-c] [-S] [-tt] [-e FILTER] [-s N] [-o FILE] { COMMAND [ARG]... | -p PID }You want to know what settings a program looks up at startup without reading its source code.
ltraceThe library-call tracer. Like strace, it controls the program through ptrace.
ltrace reads the program's ELF dynamic symbol table (.dynsym and .dynstr) to learn which library functions it imports. It starts the program under ptrace and plants breakpoint instructions (int3) on the PLT stubs, the small trampolines every call into a shared library goes through. When a breakpoint fires, the kernel stops the program and ltrace decodes the arguments using prototypes from /usr/share/ltrace/*.conf (it knows getenv takes a string, fopen two strings). It then sets a breakpoint on the return address to catch the return value. Statically linked binaries, including most Go programs, have no dynamic symbol table, so there is nothing to trace. Each traced call costs several context switches, so ltrace is slower than strace. -S adds system calls to the same output.
-e FILTEROnly these functions: getenv+fopen, or 'malloc*' patterns, or -e '@libssl.so*'-cCount calls and time per function, printed as a table at exit-SAlso show system calls (prefixed SYS_), mixed with library calls-fFollow child processes created by fork-p PIDAttach to a running process (needs root on Ubuntu)-tt / -TTimestamp each call / show time spent inside each call-s NMaximum string length to print (default 32)-n NIndent nested calls by N spaces, to see who calls whom-o FILEWrite the trace to FILE instead of stderr-x PATTERNAlso trace internal (non-PLT) functions matching the patternltrace ./myapp on a Go, Rust-musl or other static binary and assuming it does nothingStatic binaries have no PLT or dynamic symbol table, so ltrace has nothing to hook; the program's work is invisible to it.
file ./myapp to check, then strace -f for syscalls or perf record for CPURunning ltrace without -e on a real serviceYou get hundreds of thousands of strlen, memcpy and malloc calls and the program slows to a crawl.
ltrace -e getenv+fopen+connect ... or ltrace -c for a summaryReading ltrace -c times as the real cost of each functionEvery traced call pays for breakpoints and context switches; the overhead (tens of µs) dwarfs a strlen that takes nanoseconds.
Use -c for call counts; use perf to measure real CPU timeTry these on a Linux machine of your own. Each task has a hint and a solution.
Find which environment variables the date command reads.
Count the library calls made by 'ls -l ~/app' and find the most frequent one.
Show both library calls and system calls for 'cat ~/app/README.md' (or any file in ~/app), limited to fopen/open-style calls.