Ir al contenido

Ldd

Ldd is a utility that displays shared library dependencies for executable files and shared libraries. This guide covers analyzing dynamic dependencies, managing library paths, linker configuration, and troubleshooting missing libraries.

Basic Usage

Listing Dependencies

# Display dependencies for executable
ldd /bin/bash

# List dependencies for a library
ldd /lib/x86_64-linux-gnu/libc.so.6

# Display dependencies for binary in PATH
ldd /usr/bin/python3

# Show dependencies with symbol addresses
ldd /bin/ls

# Display dependencies for shared library
ldd /usr/lib/x86_64-linux-gnu/libssl.so

Basic Command Syntax

# Standard ldd usage
ldd [options] file

# Common options
ldd -v /bin/bash          # Verbose output (shows version symbols)
ldd -r /bin/bash          # Check for unused objects
ldd -u /bin/bash          # Check for undefined symbols
ldd -d /bin/bash          # Report missing objects (data relocations)
ldd -V /bin/bash          # Show version information
ldd --help                # Display help message

Understanding Ldd Output

Typical Output Example

$ ldd /bin/bash
	linux-vdso.so.1 (0x00007fff53ffe000)
	libtinfo.so.6 => /lib/x86_64-linux-gnu/libtinfo.so.6 (0x00007f8e6a000000)
	libdl.so.2 => /lib/x86_64-linux-gnu/libdl.so.2 (0x00007f8e69dfc000)
	libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f8e69c04000)
	/lib64/ld-linux-x86-64.so.2 (0x00007f8e6a1c8000)

Output Components

# Memory address in hexadecimal
(0x00007fff53ffe000)

# Library name
libtinfo.so.6

# Arrow indicates linked path (=> shows actual path if different)
=>

# Absolute path to the library file
/lib/x86_64-linux-gnu/libtinfo.so.6

# Virtual library (provided by kernel)
linux-vdso.so.1

# Dynamic linker/loader
/lib64/ld-linux-x86-64.so.2

# Not found error (when library missing)
libc.so.6 => not found

Dependency Analysis

Checking for Missing Libraries

# Check for missing dependencies
ldd /bin/bash | grep "not found"

# Show detailed missing libraries
ldd -d /usr/bin/some-binary

# Check for undefined symbols
ldd -u /bin/bash

# Force checking immediate binding
ldd -r /bin/bash

# Verbose output with all symbols
ldd -v /bin/bash | head -20

Analyzing Complex Dependencies

# Show all dependencies recursively (requires manual traversal)
ldd /usr/bin/python3
ldd /usr/lib/x86_64-linux-gnu/libpython3.9.so.1.0

# Count total dependencies
ldd /bin/bash | wc -l

# Find all binaries depending on specific library
for binary in /usr/bin/*; do
    ldd "$binary" 2>/dev/null | grep -q "libssl" && echo "$binary"
done

# List libraries with version info
ldd -v /bin/bash | grep "=>.*GLIBC"

Finding Version Information

# Show symbol versions with verbose flag
ldd -v /bin/bash

# Display version requirements
objdump -T /bin/bash | grep -i version

# Show ABI compatibility information
readelf -V /bin/bash

Library Paths

Default Library Search Paths

# Display default library path from ld.so configuration
ld --verbose | grep SEARCH_DIR | head -1

# System library directories
/lib
/lib64
/usr/lib
/usr/lib64
/usr/local/lib
/usr/local/lib64

# 32-bit libraries on 64-bit systems
/lib32
/usr/lib32

Custom Library Paths

# Using LD_LIBRARY_PATH environment variable
export LD_LIBRARY_PATH=/opt/custom/lib:/usr/local/lib:$LD_LIBRARY_PATH

# Verify path is used
ldd /bin/bash | grep custom

# Temporary override for single command
LD_LIBRARY_PATH=/opt/lib:/usr/lib ldd /bin/bash

# Prepend to default paths (safer)
export LD_LIBRARY_PATH=/opt/lib:$LD_LIBRARY_PATH

# Append to default paths
export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/opt/lib64

# Check current LD_LIBRARY_PATH
echo $LD_LIBRARY_PATH

Dynamic Linker Configuration

/etc/ld.so.conf Configuration

# View main linker configuration
cat /etc/ld.so.conf

# Display all configuration files
cat /etc/ld.so.conf
cat /etc/ld.so.conf.d/*.conf

# Typical content
/usr/local/lib
/usr/local/lib64
include /etc/ld.so.conf.d/*.conf

Managing Linker Cache

# Update linker cache (must run after changing ld.so.conf)
sudo ldconfig

# Run ldconfig in verbose mode
sudo ldconfig -v | head -20

# Display linker cache contents
ldconfig -p | head -20

# Display cache in specific directory
ldconfig -p | grep "/opt"

# Check if library is in cache
ldconfig -p | grep "libcustom"

# Print library name and real path
ldconfig -p | grep libc.so.6

Custom Library Configuration

# Create custom configuration file
sudo nano /etc/ld.so.conf.d/custom.conf

# Add custom paths
/opt/myapp/lib
/usr/local/custom/lib

# Save file and update cache
sudo ldconfig

# Verify new paths are cached
ldconfig -p | grep "/opt/myapp"

Advanced Analysis

Using objdump for Symbols

# Display all dynamic symbols
objdump -T /bin/bash | head -20

# Show imported symbols
objdump -T /bin/bash | grep UND

# Display symbol versions
objdump -T /bin/bash | grep "@@"

# Show library relocations
objdump -R /bin/bash

# Count imported functions
objdump -T /bin/bash | grep UND | wc -l

# Find version requirements for specific symbol
objdump -T /bin/bash | grep GLIBC_2.17

Using readelf for ELF Analysis

# Display dynamic section
readelf -d /bin/bash | grep NEEDED

# Show dynamic symbol table
readelf -s /bin/bash | head -20

# Display version symbols
readelf -V /bin/bash

# Show program headers
readelf -l /bin/bash | grep INTERP

# Display all dynamic information
readelf -d /bin/bash

Common Scenarios

Static vs Dynamic Linking

# Check if binary is statically linked
ldd /bin/static_binary 2>&1 | grep "not a dynamic executable"

# Dynamically linked binary (normal case)
ldd /bin/bash

# Comparison
file /bin/bash
# output: ELF 64-bit LSB executable, dynamically linked

file /bin/busybox
# output: ELF 64-bit LSB executable, statically linked

Finding Library Locations

# Find library file for dependency
find /usr -name "libc.so.6" 2>/dev/null

# Use ldconfig to locate
ldconfig -p | grep libc.so.6

# Check library version
strings /lib/x86_64-linux-gnu/libc.so.6 | grep "GLIBC"

# Locate alternative versions
find /usr -name "libc-*.so" 2>/dev/null

# Check real path (resolves symlinks)
ls -l /lib/x86_64-linux-gnu/libc.so.6

# Display file info
file /lib/x86_64-linux-gnu/libc.so.6

Troubleshooting Dependency Issues

# Binary not finding library
ldd /bin/myapp | grep "not found"

# Add library path and recheck
export LD_LIBRARY_PATH=/opt/lib:$LD_LIBRARY_PATH
ldd /bin/myapp | grep "not found"

# Update system cache if installed to standard path
sudo ldconfig

# Check library version compatibility
ldd -v /bin/myapp | grep "=>"

# Verify library is executable
file /lib/x86_64-linux-gnu/libc.so.6

# Check library symbols
strings /lib/x86_64-linux-gnu/libc.so.6 | grep "GLIBC_2"

Library Version Management

Checking GLIBC Version

# Display GLIBC version
ldd --version

# Show in detail
strings /lib/x86_64-linux-gnu/libc.so.6 | grep "GLIBC_"

# Count available versions
strings /lib/x86_64-linux-gnu/libc.so.6 | grep "GLIBC_" | sort -u | wc -l

# Find minimum GLIBC required by binary
objdump -T /bin/bash | grep "GLIBC" | awk '{print $NF}' | sort -u

Handling Multiple Library Versions

# List available library versions
ls -la /lib/x86_64-linux-gnu/libc*

# Check symlink resolution
readlink /lib/x86_64-linux-gnu/libc.so.6

# Verify correct version is used
ldd -v /bin/bash | grep libc.so

# Override for testing
LD_LIBRARY_PATH=/opt/experimental/lib:$LD_LIBRARY_PATH ldd /bin/bash

Performance and Debugging

Profiling Library Loading

# Show library load order and timing
strace -e openat ldd /bin/bash 2>&1 | grep ".so"

# Debug symbol resolution
ldd -v /bin/bash 2>&1 | grep -A 5 "Symbol table"

# Trace linker operations
LD_DEBUG=all /bin/bash -c "echo test" 2>&1 | head -30

# Debug specific categories
LD_DEBUG=libs /bin/bash -c "echo test" 2>&1 | head -20

# Verbose linker information
LD_DEBUG=symbols /bin/bash -c "echo test" 2>&1 | head -20

Reducing Dependencies

# Find unused libraries (if supported by binary)
ldd -u /usr/bin/python3

# Show relocations that might not be needed
objdump -R /bin/bash | head -10

# Test if library can be removed (dangerous!)
LD_PRELOAD=/nonexistent.so /bin/bash -c "echo test"

# Check for lazy binding
readelf -d /bin/bash | grep BIND

Security Considerations

Verifying Library Integrity

# Check for library modifications
md5sum /lib/x86_64-linux-gnu/libc.so.6

# Verify against package database (Debian)
sudo debsums -c /libc6

# Display library checksums
sha256sum /lib/x86_64-linux-gnu/libc.so.6

# Compare with package manifest
dpkg -L libc6 | grep libc.so.6

Preventing Library Injection

# Check for LD_PRELOAD usage
env | grep LD_

# Unset potentially dangerous variables before running
unset LD_PRELOAD
unset LD_LIBRARY_PATH
/bin/bash

# Run with minimal environment
env -i /bin/bash -c "ldd /bin/bash"

# Securely check dependencies
strace -e open,openat /bin/bash -c "echo test" 2>&1 | grep ".so"

Practical Examples

Complete Application Analysis

#!/bin/bash
# Analyze all dependencies for an application

APP="/usr/bin/python3"

echo "=== Direct Dependencies ==="
ldd "$APP" | grep "=>"

echo "=== Missing Libraries ==="
ldd "$APP" 2>&1 | grep "not found" || echo "All dependencies found"

echo "=== Version Requirements ==="
ldd -v "$APP" 2>&1 | grep "GLIBC" | head -5

echo "=== Library Paths Used ==="
ldd "$APP" | awk '{print $3}' | sort -u

echo "=== Total Dependencies ==="
ldd "$APP" | wc -l

Finding Incompatible Dependencies

#!/bin/bash
# Check binary for unmet dependencies

BINARY="$1"

if [ -z "$BINARY" ]; then
    echo "Usage: $0 <binary>"
    exit 1
fi

echo "Checking dependencies for $BINARY..."
ldd "$BINARY" | grep -i "not found"

if [ $? -eq 1 ]; then
    echo "All dependencies resolved"
else
    echo "ERROR: Missing dependencies detected"
    exit 1
fi

Linker Configuration Script

#!/bin/bash
# Add custom library path to system configuration

NEW_PATH="/opt/myapp/lib"

if ! grep -q "$NEW_PATH" /etc/ld.so.conf.d/*; then
    echo "Adding $NEW_PATH to linker configuration..."
    echo "$NEW_PATH" | sudo tee -a /etc/ld.so.conf.d/custom.conf > /dev/null

    echo "Updating linker cache..."
    sudo ldconfig

    echo "Verifying..."
    ldconfig -p | grep "$NEW_PATH"
else
    echo "$NEW_PATH already configured"
fi

Troubleshooting

Common Issues

# Issue: "GLIBCXX_3.4.21 not found"
# Solution: Update libstdc++
sudo apt install libstdc++6

# Issue: "libc.so.6: version `GLIBC_2.29' not found"
# Solution: Update glibc (risky - be careful)
sudo apt install libc6

# Issue: Library in custom path not found
# Solution: Update ld.so.conf and run ldconfig
echo "/opt/lib" | sudo tee -a /etc/ld.so.conf.d/custom.conf
sudo ldconfig

# Issue: "cannot execute binary file"
# Solution: Check architecture
file /path/to/binary
ldd /path/to/binary

Debugging Library Loading

# Enable linker debugging
export LD_DEBUG=all
/bin/bash -c "ldd /bin/bash" 2>&1 | grep "binding"

# Check specific library
export LD_DEBUG=libs
/bin/bash -c "echo test" 2>&1 | grep "libc"

# Show relocations
export LD_DEBUG=reloc
/bin/bash -c "echo test" 2>&1 | head -30

# Disable to restore normal operation
unset LD_DEBUG

Resources


Last updated: 2025-03-30