Home / Alt manpages / pldd(1)

  • pldd(1)
  • User command
  • linux

Inspect a Process's Loaded Libraries with pldd

A service is misbehaving and you suspect it picked up the wrong shared library somewhere along the way. pldd lists the dynamic shared objects a running Linux process actually has loaded, and this shows you how to read the result and recognise a permissions failure for what it is. The examples use pldd from glibc 2.39 on this machine, with man-pages 6.7-2 supplying the installed manual page.

Allow about ten minutes. You need a shell and a process ID for something you are allowed to inspect. The normal checks are read-only and do not need sudo. Do not reach for elevated privileges as a reflex: changing privilege can change which process information is visible, and make a test less representative of the service you are actually investigating.

1. Confirm the installed command

Start by checking which executable will run and which glibc build supplies it:

$ command -v pldd
/usr/bin/pldd
$ pldd --version
pldd (Ubuntu GLIBC 2.39-0ubuntu8.9) 2.39

The manual's interface is deliberately small. The normal form is pldd PID. The read-only information options are --help or -?, --usage, and --version or -V. There is no library-name filter, and no option that makes an inaccessible process suddenly readable.

Checkpoint: if command -v pldd finds nothing, install or repair the glibc utilities from your distribution before going further. Do not paper over a path problem by copying a different pldd binary into /usr/local/bin.

2. Choose a process you can identify

A PID is just a number, and it gets reused once a process exits. Check the command line and owner immediately before running pldd:

$ PID=12345
$ ps -p "$PID" -o pid=,user=,comm=,args=
  12345 appuser  my-service       /usr/local/bin/my-service --config /etc/my-service.conf

Swap 12345 for a real PID on your own host; treat the output above as a shape, not a literal value, since the owner, command and arguments will differ. If ps prints no row, the process has already gone, or the PID was wrong from the start. Find a fresh PID rather than reusing a stale number.

A process you started yourself, under your own account, is usually the simplest test target. Inspecting another user's process, a set-user-ID process, or one running in a more restricted service environment may fail even when the PID genuinely exists.

3. List the process's dynamic objects

Run pldd against the verified PID:

$ pldd "$PID"
12345:   /usr/local/bin/my-service
linux-vdso.so.1
/lib/x86_64-linux-gnu/libpthread.so.0
/lib/x86_64-linux-gnu/libc.so.6
/lib64/ld-linux-x86-64.so.2

The first line identifies the process, and the rest are the dynamic shared objects currently linked into it. This list includes anything loaded later with dlopen(3), so it can show more than a static inspection of the executable would.

Names and paths shift with the program, architecture, distribution and runtime activity. A virtual object such as linux-vdso.so.1 is completely normal. Do not compare this line-for-line against another machine and call the mismatch a fault.

Checkpoint: capture the command and its output with a timestamp and PID if you are attaching it to an incident record:

$ date -Is
$ printf 'PID: %s\n' "$PID"
$ pldd "$PID"; printf 'pldd exit status: %s\n' "$?"
2026-09-26T12:00:00+01:00
PID: 12345
12345:   /usr/local/bin/my-service
...library lines vary...
pldd exit status: 0

4. Read failures as access or lifetime problems

The installed manual documents exit status 1 for a process that does not exist, one whose dynamic-object list you cannot access, or a missing argument. Status 64 means an invalid option. Check the status rather than treating a quiet terminal as a successful result:

$ pldd 999999
pldd: cannot attach to process 999999: No such file or directory
$ printf 'exit status: %s\n' "$?"
exit status: 1

The wording depends on the kernel and glibc build. What actually matters is the non-zero status, and whether the PID still identifies the process you meant. Rerun ps first, then check the process owner against your own account. On systems with ptrace restrictions, a process can exist and still refuse inspection outright: this host, for example, reports Operation not permitted when you point pldd at the current shell.

Do not "fix" this by attaching to a production service with sudo without approval. Elevated inspection can expose sensitive process details, and a permission policy may be deliberately protecting that service. If access is authorised, follow the host's documented debugging procedure and record who approved it. There is nothing to undo when pldd merely fails to read a process.

5. Use alternatives when pldd is not enough

pldd answers one narrow question: which dynamic objects are linked into this process. It will not show symbol versions, explain why a library was chosen, or list every file the process has open. The manual points to lsof -p PID for a broader open-file view, and to GDB's info shared for debugger-oriented shared-library information.

$ lsof -p "$PID"
$ gdb -q -batch -ex 'set confirm off' -ex 'set height 0' \
    -ex 'info shared' -ex quit -p "$PID"

Both may need separate packages and permissions, and both can attach to a live service with real operational or security consequences. Reach for them only once the narrower pldd output has left a specific question unanswered.

Done means

  • You confirmed the installed pldd path and glibc version.
  • You checked that the PID still belongs to the process you meant to inspect.
  • You captured the shared-object list and checked the exit status.
  • You can tell a vanished or inaccessible process apart from a genuinely missing library.
  • You have not changed the process, its libraries, or any persistent system configuration.