DZone
Thanks for visiting DZone today,
Edit Profile
  • Manage Email Subscriptions
  • How to Post to DZone
  • Article Submission Guidelines
Sign Out View Profile
  • Post an Article
  • Manage My Drafts
Over 2 million developers have joined DZone.
Log In / Join
Please enter at least three characters to search
Refcards Trend Reports
Events Video Library
Refcards
Trend Reports

Events

View Events Video Library

Zones

Culture and Methodologies Agile Career Development Methodologies Team Management
Data Engineering AI/ML Big Data Data Databases IoT
Software Design and Architecture Cloud Architecture Containers Integration Microservices Performance Security
Coding Frameworks Java JavaScript Languages Tools
Testing, Deployment, and Maintenance Deployment DevOps and CI/CD Maintenance Monitoring and Observability Testing, Tools, and Frameworks
Culture and Methodologies
Agile Career Development Methodologies Team Management
Data Engineering
AI/ML Big Data Data Databases IoT
Software Design and Architecture
Cloud Architecture Containers Integration Microservices Performance Security
Coding
Frameworks Java JavaScript Languages Tools
Testing, Deployment, and Maintenance
Deployment DevOps and CI/CD Maintenance Monitoring and Observability Testing, Tools, and Frameworks

Modernize your data layer. Learn how to design cloud-native database architectures to meet the evolving demands of AI and GenAI workkloads.

Secure your stack and shape the future! Help dev teams across the globe navigate their software supply chain security challenges.

Releasing software shouldn't be stressful or risky. Learn how to leverage progressive delivery techniques to ensure safer deployments.

Avoid machine learning mistakes and boost model performance! Discover key ML patterns, anti-patterns, data strategies, and more.

Related

  • While Performing Dependency Selection, I Avoid the Loss Of Sleep From Node.js Libraries' Dangers
  • Why You Don’t Need That New JavaScript Library
  • Why Use AWS Lambda Layers? Advantages and Considerations
  • Monitoring Dynamic Linker Hijacking With eBPF

Trending

  • How to Submit a Post to DZone
  • Docker Base Images Demystified: A Practical Guide
  • How Large Tech Companies Architect Resilient Systems for Millions of Users
  • Unlocking AI Coding Assistants Part 4: Generate Spring Boot Application
  1. DZone
  2. Coding
  3. Tools
  4. Understanding ldd: The Linux Dynamic Dependency Explorer

Understanding ldd: The Linux Dynamic Dependency Explorer

The Linux command ldd is a versatile utility that lists dynamic library dependencies for executables, helping users identify what shared libraries a program needs to run.

By 
Ajinkya K user avatar
Ajinkya K
·
Apr. 03, 25 · Analysis
Likes (3)
Comment
Save
Tweet
Share
4.5K Views

Join the DZone community and get the full member experience.

Join For Free

In the world of Linux system administration and software development, understanding how executables interact with shared libraries is crucial. Enter ldd (List Dynamic Dependencies), a powerful command-line utility that helps you peer into the complex web of library dependencies that make your applications run. 

In this comprehensive guide, we'll explore ldd, its usage, security considerations, and how it can help you solve common problems.

What Is ldd?

ldd is a shell script that displays the shared libraries required by an executable or shared library. It helps answer the fundamental question: "What libraries does this program need to run?" This information is vital for troubleshooting missing dependencies, analyzing software, or preparing applications for deployment.

Under the hood, ldd uses the dynamic linker (typically /lib/ld-linux.so.2 or /lib64/ld-linux-x86-64.so.2 on most Linux systems) to resolve and list dependencies. It's part of the GNU C Library (glibc) package and comes pre-installed on most Linux distributions.

Basic Usage

The basic syntax of ldd is straightforward:

Shell
 
ldd [options] filename


For example, to check the dependencies of the ls command:

Shell
 
$ ldd /bin/ls
        linux-vdso.so.1 (0x00007ffd53bc9000)
        libselinux.so.1 => /lib/x86_64-linux-gnu/libselinux.so.1 (0x00007f87bdfea000)
        libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f87bddf8000)
        libpcre2-8.so.0 => /lib/x86_64-linux-gnu/libpcre2-8.so.0 (0x00007f87bdd61000)
        /lib64/ld-linux-x86-64.so.2 (0x00007f87be046000)


The output shows:

  • The name of each required shared library
  • The path where the library was found (after =>)
  • The memory address where the library would be loaded (in parentheses)

Some special entries you might see:

  • linux-vdso.so.1: The virtual dynamic shared object, a special library provided by the kernel
  • /lib64/ld-linux-x86-64.so.2: The dynamic linker itself, which loads all the other libraries

Useful Options

ldd offers several options that expand its functionality:

  • --version: Display the version of ldd
  • --help: Show a help message
  • -v or --verbose: Print all information, including symbol versioning
  • -u or --unused: Print unused direct dependencies
  • -d or --data-relocs: Perform data relocations and report missing objects
  • -r or --function-relocs: Perform relocations for both data objects and functions, and report missing objects and functions

The verbose option can be particularly useful:

Shell
 
$ ldd -v /bin/ls
        linux-vdso.so.1 (0x00007ffcb17fc000)
        libselinux.so.1 => /lib/x86_64-linux-gnu/libselinux.so.1 (0x00007f441f1fa000)
        libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f441f008000)
        libpcre2-8.so.0 => /lib/x86_64-linux-gnu/libpcre2-8.so.0 (0x00007f441ef71000)
        /lib64/ld-linux-x86-64.so.2 (0x00007f441f256000)

        Version information:
        /bin/ls:
                libselinux.so.1 (LIBSELINUX_1.0) => /lib/x86_64-linux-gnu/libselinux.so.1
                libc.so.6 (GLIBC_2.14) => /lib/x86_64-linux-gnu/libc.so.6
                libc.so.6 (GLIBC_2.3.4) => /lib/x86_64-linux-gnu/libc.so.6
                libc.so.6 (GLIBC_2.4) => /lib/x86_64-linux-gnu/libc.so.6
                libc.so.6 (GLIBC_2.2.5) => /lib/x86_64-linux-gnu/libc.so.6
...


This shows not only the libraries but also the specific versions of symbols required from each library.

How ldd Works

Understanding how ldd works can help you use it more effectively:

  1. ldd is primarily a shell script that wraps around the dynamic linker.
  2. It sets the LD_TRACE_LOADED_OBJECTS environment variable to 1.
  3. This special environment variable tells the dynamic linker to print the libraries it would load rather than actually running the program.
  4. The dynamic linker processes the executable, identifies all dependencies, resolves them against the library search path, and prints the results.

The library search path includes directories specified in:

  • The executable's rpath (embedded in the binary)
  • The LD_LIBRARY_PATH environment variable
  • The system's /etc/ld.so.conf file and /etc/ld.so.conf.d/ directory
  • The standard system library directories (/lib, /usr/lib, etc.)

Security Considerations

It's important to note that ldd has significant security implications. When ldd examines an executable, in some implementations or older versions, it may actually load and execute code from the binary and its libraries.

This means that running ldd on an untrusted executable could potentially execute malicious code. As the ldd man page warns:

Be aware that in some circumstances, the symbols shown in the ldd output might not exactly match the symbols that would be used at runtime.

For security reasons, never run ldd on untrusted executables. Instead, consider safer alternatives:

  1. Use objdump -p /path/to/executable | grep NEEDED to list required libraries without loading them.
  2. Use readelf -d /path/to/executable | grep NEEDED for similar information.
  3. On newer systems, use ldd with the --no-execute option if available.

Common Use Cases

1. Troubleshooting "Missing Library" Errors

One of the most common uses of ldd is to diagnose errors like:

Shell
 
error while loading shared libraries: libfoo.so.1: cannot open shared object file: No such file or directory


Using ldd on the executable will show which libraries are missing or not being found:

Shell
 
$ ldd /path/to/program
        libfoo.so.1 => not found


This tells you that you need to install the package containing libfoo.so.1 or adjust your library search path.

2. Checking for Unnecessary Dependencies

The -u option helps identify libraries that are linked but not actually used:

Shell
 
$ ldd -u /path/to/program
Unused direct dependencies:
        /usr/lib/libunneeded.so


This can help streamline applications by removing unnecessary links.

3. Preparing Application Deployment

When deploying applications to different systems, ldd helps identify all libraries that need to be included:

Shell
 
$ ldd /path/to/app > required_libraries.txt


You can then ensure that all these libraries are available on the target system.

4. Verifying Library Compatibility

The -v option shows version information, helping you confirm that your executable is compatible with the installed libraries:

Shell
 
$ ldd -v /path/to/app


This is useful when migrating applications between different versions of Linux distributions.

Common Issues and Solutions

Missing Libraries

If ldd shows "not found" for a library:

  1. Install the appropriate package:

    Shell
     
    sudo apt-get install libfoo-dev  # Debian/Ubuntu
    sudo yum install libfoo-devel    # RHEL/CentOS
  2. If the library is installed but not found, update the library cache:

    Shell
     
    sudo ldconfig
  3. For custom library locations, add the path to /etc/ld.so.conf.d/ and run ldconfig.

Wrong Library Version

If the program requires a specific version of a library:

  1. Check the installed version with ldconfig -v | grep libname.
  2. Install the correct version from repositories or build from source.
  3. Consider using LD_LIBRARY_PATHto point to the correct library version:
    Shell
     
    LD_LIBRARY_PATH=/path/to/correct/version ./program

Too Many Dependencies

If your program has an excessive number of dependencies:

  1. Use static linking for some libraries.
  2. Refactor to reduce dependencies.
  3. Consider using containers or application bundles.

Beyond ldd: Related Tools

While ldd is invaluable, several other tools complement its functionality:

  • ldconfig: Updates the library cache and shows currently installed libraries
  • nm: Lists symbols in object files
  • objdump: Displays information about object files
  • readelf: Shows information about ELF format files
  • patchelf: Modifies ELF binaries (useful for changing rpath values)
  • strace -e trace=open,access: Traces actual file access attempts during program execution

Inside Dynamic Libraries

To better understand what ldd is showing, it helps to know how dynamic libraries work:

  1. Naming convention: Libraries follow the pattern libname.so.major.minor.patch.
  2. soname: The major version identifies the ABI compatibility.
  3. Symbol versioning: Allows multiple versions of functions to coexist.
  4. RPATH/RUNPATH: Embedded paths in executables that tell the linker where to find libraries.
  5. Lazy binding: Functions are only resolved when first called, improving startup time.

You can examine these details with:

Shell
 
$ readelf -d /path/to/library.so


Advanced ldd Usage

Analyzing Complex Applications

For large applications with many components, create a dependency graph:

Shell
 
#!/bin/bash
function get_deps() {
    ldd "$1" | awk '{if(NF>=4) print $3; else if(NF==2) print $1}' | grep -v "^$"
}

MAIN_EXE=$1
echo "digraph dependencies {"
echo "  \"$MAIN_EXE\" [shape=box];"
for lib in $(get_deps "$MAIN_EXE" | sort | uniq); do
    if [ -f "$lib" ]; then
        echo "  \"$MAIN_EXE\" -> \"$lib\";"
        for sublib in $(get_deps "$lib" | sort | uniq); do
            if [ -f "$sublib" ]; then
                echo "  \"$lib\" -> \"$sublib\";"
            fi
        done
    fi
done
echo "}"


Save this as ldd-graph.sh, make it executable, and run:

Shell
 
./ldd-graph.sh /path/to/executable | dot -Tpng > dependencies.png


This creates a visual map of your application's dependencies. Note that you need graphviz installed for the above command for it to work.

Example dependency graph for /bin/ls is as follows:

Dependency graph for the ls command

Auditing System Security

Check all executables in a directory for suspicious dependencies:

Shell
 
#!/bin/bash
for file in $(find /path/to/check -type f -executable); do
    if file "$file" | grep -q "ELF"; then
        echo "Checking $file"
        ldd "$file" 2>/dev/null | grep -v linux-vdso | grep -E '(not found|//)'
    fi
done


This helps identify missing or potentially dangerous library references.

Conclusion

ldd is a powerful tool that provides visibility into the complex world of shared libraries and dynamic linking on Linux systems. Whether you're troubleshooting runtime errors, preparing applications for deployment, or analyzing software dependencies, understanding how to use ldd effectively can save hours of debugging time.

Remember to use ldd with caution on untrusted executables, and complement it with other tools like readelf and objdump for a complete picture of your application's requirements. By mastering ldd, you'll have a valuable skill in your Linux toolkit that helps demystify one of the most fundamental aspects of how programs work.

Quick Reference

Command Purpose
ldd executable List all dependencies
ldd -v executable Show verbose information, including versions
ldd -u executable Show unused dependencies
objdump -p executable | grep NEEDED Safer alternative for untrusted files
readelf -d executable | grep NEEDED Another safe alternative
ldconfig -v | grep libname Find installed library locations
LD_LIBRARY_PATH=/path ./program Run with custom library path
Library Dependency Linux (operating system)

Opinions expressed by DZone contributors are their own.

Related

  • While Performing Dependency Selection, I Avoid the Loss Of Sleep From Node.js Libraries' Dangers
  • Why You Don’t Need That New JavaScript Library
  • Why Use AWS Lambda Layers? Advantages and Considerations
  • Monitoring Dynamic Linker Hijacking With eBPF

Partner Resources

×

Comments
Oops! Something Went Wrong

The likes didn't load as expected. Please refresh the page and try again.

ABOUT US

  • About DZone
  • Support and feedback
  • Community research
  • Sitemap

ADVERTISE

  • Advertise with DZone

CONTRIBUTE ON DZONE

  • Article Submission Guidelines
  • Become a Contributor
  • Core Program
  • Visit the Writers' Zone

LEGAL

  • Terms of Service
  • Privacy Policy

CONTACT US

  • 3343 Perimeter Hill Drive
  • Suite 100
  • Nashville, TN 37211
  • support@dzone.com

Let's be friends:

Likes
There are no likes...yet! 👀
Be the first to like this post!
It looks like you're not logged in.
Sign in to see who liked this post!