Inspect a Process's Loaded Libraries with pldd
You will finish with a repeatable way to list the dynamic shared objects loaded by a Linux process, recognise a permissions failure, and record a useful result for troubleshooting. The examples use pldd from glibc 2.39 on this machine, with man-pages 6.7-2 supplying the installed manual page.
The route
Jump straight to the step you need, or tick off Done means at the end.
Allow about ten minutes. You need a shell and a process ID for a process you are allowed to inspect. The normal checks are read-only and do not need sudo. Do not use elevated privileges as a reflex: changing privilege can change which process information is visible and can make a test less representative of the service you are investigating.
1. Confirm the installed command
Start by checking which executable will run and which glibc build provides it:
$ command -v pldd
/usr/bin/pldd
$ pldd --version
pldd (Ubuntu GLIBC 2.39-0ubuntu8.9) 2.39
The manual's interface is 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 readable.
Checkpoint: if command -v pldd finds nothing, install or repair the glibc utilities supplied by your distribution before continuing. Do not copy a different pldd binary into /usr/local/bin just to get past a path problem.
2. Choose a process you can identify
A PID is just a number, and it can be reused after a process exits. Inspect 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
Replace 12345 with an existing PID from your own host. Treat the output as an example: the owner, command and arguments will be different. If ps prints no row, the process has gone away or the PID was wrong. Find a fresh PID rather than reusing the number blindly.
A process you started from the same user account is usually the simplest test target. Inspecting another user's process, a set-user-ID process, or a process in a more restricted service environment may fail even when the PID exists.
3. List the process's dynamic objects
Run pldd with 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. The following lines are the dynamic shared objects currently linked into it. The list includes objects loaded later with dlopen(3), so it can contain more than the libraries visible from a static inspection of the executable.
Names and paths vary with the program, architecture, distribution and runtime activity. A virtual object such as linux-vdso.so.1 is normal. Do not compare the example line-for-line with another machine and call the difference a fault.
Checkpoint: preserve the command and its output with the time 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 when the process does not exist, when you cannot access its dynamic-object list, or when no argument is supplied. It documents status 64 for an invalid option. Check the status instead of treating an empty-looking 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. The useful facts are the non-zero status and whether the PID still identifies the intended process. Re-run ps first, then check the process owner and your account. On systems with ptrace restrictions, a process can exist but still reject inspection. This host, for example, reports Operation not permitted when the current shell is passed to pldd.
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 the service. If access is authorised, use the host's documented debugging procedure and record who approved it. There is no state to undo when pldd merely fails to read a process.
5. Use alternatives when pldd is not enough
pldd answers one focused question: which dynamic objects are linked into this process? It does not show symbol versions, why a library was selected, or every file opened by the process. 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"
These alternatives may need separate packages and permissions. They can also attach to a live service, which may have operational or security consequences. Use them only when the narrower pldd output leaves a specific question unanswered.
Done means
- You confirmed the installed
plddpath and glibc version. - You checked that the PID still belongs to the intended process.
- You captured the shared-object list and checked the exit status.
- You can distinguish a vanished or inaccessible process from a missing library.
- You have not changed the process, its libraries, or persistent system configuration.